前提

Java反射的API在JavaSE1.7的时候已经基本完善,但是本文编写的时候使用的是Oracle JDK11,因为JDK11对于sun包下的源码也上传了,可以直接通过IDE查看对应的源码和进行Debug。

本文主要介绍反射调用的底层实现,当然还没有能力分析JVM的实现,这里只分析到最终Native方法的调用点。底层会依赖到Unsafe类,可以的话可以看下笔者之前写的一篇文章《神奇的魔法类和双刃剑-Unsafe》。

反射调用的底层实现探究

主要考虑下面的情况:

  • 属性操作:java.lang.reflect.Field#set(Object obj, Object value)java.lang.reflect.Field#get(Object obj)
  • 构造器调用:java.lang.reflect.Constructor#newInstance(Object ... initargs)
  • 方法调用:java.lang.reflect.Method#invoke(Object obj, Object... args)

处理属性操作的底层实现

属性操作方法Field#set(Object obj, Object value)Field#get(Object obj)底层都是委托到jdk.internal.reflect.FieldAccessor实现:

public interface FieldAccessor {
/** Matches specification in {@link java.lang.reflect.Field} */
public Object get(Object obj) throws IllegalArgumentException; /** Matches specification in {@link java.lang.reflect.Field} */
public boolean getBoolean(Object obj) throws IllegalArgumentException; /** Matches specification in {@link java.lang.reflect.Field} */
public byte getByte(Object obj) throws IllegalArgumentException; /** Matches specification in {@link java.lang.reflect.Field} */
public char getChar(Object obj) throws IllegalArgumentException; /** Matches specification in {@link java.lang.reflect.Field} */
public short getShort(Object obj) throws IllegalArgumentException; /** Matches specification in {@link java.lang.reflect.Field} */
public int getInt(Object obj) throws IllegalArgumentException; /** Matches specification in {@link java.lang.reflect.Field} */
public long getLong(Object obj) throws IllegalArgumentException; /** Matches specification in {@link java.lang.reflect.Field} */
public float getFloat(Object obj) throws IllegalArgumentException; /** Matches specification in {@link java.lang.reflect.Field} */
public double getDouble(Object obj) throws IllegalArgumentException; /** Matches specification in {@link java.lang.reflect.Field} */
public void set(Object obj, Object value)
throws IllegalArgumentException, IllegalAccessException; /** Matches specification in {@link java.lang.reflect.Field} */
public void setBoolean(Object obj, boolean z)
throws IllegalArgumentException, IllegalAccessException; /** Matches specification in {@link java.lang.reflect.Field} */
public void setByte(Object obj, byte b)
throws IllegalArgumentException, IllegalAccessException; /** Matches specification in {@link java.lang.reflect.Field} */
public void setChar(Object obj, char c)
throws IllegalArgumentException, IllegalAccessException; /** Matches specification in {@link java.lang.reflect.Field} */
public void setShort(Object obj, short s)
throws IllegalArgumentException, IllegalAccessException; /** Matches specification in {@link java.lang.reflect.Field} */
public void setInt(Object obj, int i)
throws IllegalArgumentException, IllegalAccessException; /** Matches specification in {@link java.lang.reflect.Field} */
public void setLong(Object obj, long l)
throws IllegalArgumentException, IllegalAccessException; /** Matches specification in {@link java.lang.reflect.Field} */
public void setFloat(Object obj, float f)
throws IllegalArgumentException, IllegalAccessException; /** Matches specification in {@link java.lang.reflect.Field} */
public void setDouble(Object obj, double d)
throws IllegalArgumentException, IllegalAccessException;
}

FieldAccessor接口有很多的实现,FieldAccessor接口实例是通过jdk.internal.reflect.ReflectionFactory这个工厂构造的:

    public FieldAccessor newFieldAccessor(Field field, boolean override) {
checkInitted(); Field root = langReflectAccess.getRoot(field);
if (root != null) {
// FieldAccessor will use the root unless the modifiers have
// been overrridden
if (root.getModifiers() == field.getModifiers() || !override) {
field = root;
}
}
return UnsafeFieldAccessorFactory.newFieldAccessor(field, override);
}

最终委托到UnsafeFieldAccessorFactory#newFieldAccessor()

class UnsafeFieldAccessorFactory {
static FieldAccessor newFieldAccessor(Field field, boolean override) {
Class<?> type = field.getType();
boolean isStatic = Modifier.isStatic(field.getModifiers());
boolean isFinal = Modifier.isFinal(field.getModifiers());
boolean isVolatile = Modifier.isVolatile(field.getModifiers());
boolean isQualified = isFinal || isVolatile;
boolean isReadOnly = isFinal && (isStatic || !override);
if (isStatic) {
// This code path does not guarantee that the field's
// declaring class has been initialized, but it must be
// before performing reflective operations.
UnsafeFieldAccessorImpl.unsafe.ensureClassInitialized(field.getDeclaringClass()); if (!isQualified) {
if (type == Boolean.TYPE) {
return new UnsafeStaticBooleanFieldAccessorImpl(field);
} else if (type == Byte.TYPE) {
return new UnsafeStaticByteFieldAccessorImpl(field);
} else if (type == Short.TYPE) {
return new UnsafeStaticShortFieldAccessorImpl(field);
} else if (type == Character.TYPE) {
return new UnsafeStaticCharacterFieldAccessorImpl(field);
} else if (type == Integer.TYPE) {
return new UnsafeStaticIntegerFieldAccessorImpl(field);
} else if (type == Long.TYPE) {
return new UnsafeStaticLongFieldAccessorImpl(field);
} else if (type == Float.TYPE) {
return new UnsafeStaticFloatFieldAccessorImpl(field);
} else if (type == Double.TYPE) {
return new UnsafeStaticDoubleFieldAccessorImpl(field);
} else {
return new UnsafeStaticObjectFieldAccessorImpl(field);
}
} else {
if (type == Boolean.TYPE) {
return new UnsafeQualifiedStaticBooleanFieldAccessorImpl(field, isReadOnly);
} else if (type == Byte.TYPE) {
return new UnsafeQualifiedStaticByteFieldAccessorImpl(field, isReadOnly);
} else if (type == Short.TYPE) {
return new UnsafeQualifiedStaticShortFieldAccessorImpl(field, isReadOnly);
} else if (type == Character.TYPE) {
return new UnsafeQualifiedStaticCharacterFieldAccessorImpl(field, isReadOnly);
} else if (type == Integer.TYPE) {
return new UnsafeQualifiedStaticIntegerFieldAccessorImpl(field, isReadOnly);
} else if (type == Long.TYPE) {
return new UnsafeQualifiedStaticLongFieldAccessorImpl(field, isReadOnly);
} else if (type == Float.TYPE) {
return new UnsafeQualifiedStaticFloatFieldAccessorImpl(field, isReadOnly);
} else if (type == Double.TYPE) {
return new UnsafeQualifiedStaticDoubleFieldAccessorImpl(field, isReadOnly);
} else {
return new UnsafeQualifiedStaticObjectFieldAccessorImpl(field, isReadOnly);
}
}
} else {
if (!isQualified) {
if (type == Boolean.TYPE) {
return new UnsafeBooleanFieldAccessorImpl(field);
} else if (type == Byte.TYPE) {
return new UnsafeByteFieldAccessorImpl(field);
} else if (type == Short.TYPE) {
return new UnsafeShortFieldAccessorImpl(field);
} else if (type == Character.TYPE) {
return new UnsafeCharacterFieldAccessorImpl(field);
} else if (type == Integer.TYPE) {
return new UnsafeIntegerFieldAccessorImpl(field);
} else if (type == Long.TYPE) {
return new UnsafeLongFieldAccessorImpl(field);
} else if (type == Float.TYPE) {
return new UnsafeFloatFieldAccessorImpl(field);
} else if (type == Double.TYPE) {
return new UnsafeDoubleFieldAccessorImpl(field);
} else {
return new UnsafeObjectFieldAccessorImpl(field);
}
} else {
if (type == Boolean.TYPE) {
return new UnsafeQualifiedBooleanFieldAccessorImpl(field, isReadOnly);
} else if (type == Byte.TYPE) {
return new UnsafeQualifiedByteFieldAccessorImpl(field, isReadOnly);
} else if (type == Short.TYPE) {
return new UnsafeQualifiedShortFieldAccessorImpl(field, isReadOnly);
} else if (type == Character.TYPE) {
return new UnsafeQualifiedCharacterFieldAccessorImpl(field, isReadOnly);
} else if (type == Integer.TYPE) {
return new UnsafeQualifiedIntegerFieldAccessorImpl(field, isReadOnly);
} else if (type == Long.TYPE) {
return new UnsafeQualifiedLongFieldAccessorImpl(field, isReadOnly);
} else if (type == Float.TYPE) {
return new UnsafeQualifiedFloatFieldAccessorImpl(field, isReadOnly);
} else if (type == Double.TYPE) {
return new UnsafeQualifiedDoubleFieldAccessorImpl(field, isReadOnly);
} else {
return new UnsafeQualifiedObjectFieldAccessorImpl(field, isReadOnly);
}
}
}
}
}

这里注意一下属性修饰符的判断:

  • isStatic:静态属性,也就是static关键字修饰的属性。
  • isFinal:final关键字修饰的属性。
  • isVolatile:valatile关键字修饰的属性。
  • isQualified:valatile关键字或者final关键字修饰的属性。
  • isReadOnly:是否只读属性,final关键字修饰的属性或者static关键字修饰并且不能覆盖(override = false)的属性。

通过上面修饰符做判断,得到最终的FieldAccessor实现。这里挑一个例子进行分析,例如一个普通非静态没有volatile和final关键字修饰属性最终就会得到UnsafeObjectFieldAccessorImpl的实例:

class UnsafeObjectFieldAccessorImpl extends UnsafeFieldAccessorImpl {
UnsafeObjectFieldAccessorImpl(Field field) {
super(field);
} public Object get(Object obj) throws IllegalArgumentException {
ensureObj(obj);
return unsafe.getObject(obj, fieldOffset);
} public void set(Object obj, Object value)
throws IllegalArgumentException, IllegalAccessException{
ensureObj(obj);
if (isFinal) {
throwFinalFieldIllegalAccessException(value);
}
if (value != null) {
if (!field.getType().isAssignableFrom(value.getClass())) {
throwSetIllegalArgumentException(value);
}
}
unsafe.putObject(obj, fieldOffset, value);
} public boolean getBoolean(Object obj) throws IllegalArgumentException {
throw newGetBooleanIllegalArgumentException();
} public byte getByte(Object obj) throws IllegalArgumentException {
throw newGetByteIllegalArgumentException();
} // 省略其他直接抛出异常的方法
}

可见UnsafeObjectFieldAccessorImpl中除了get(Object obj)set(Object obj, Object value)方法,其他方法都是直接抛出IllegalArgumentException。而get(Object obj)set(Object obj, Object value)底层分别依赖于jdk.internal.misc.UnsafeputObject(obj, fieldOffset, value)getObject(obj, fieldOffset)方法。而属性的内存偏移地址是在UnsafeObjectFieldAccessorImpl的父类UnsafeFieldAccessorImpl的构造函数中计算出来的:

abstract class UnsafeFieldAccessorImpl extends FieldAccessorImpl {
static final Unsafe unsafe = Unsafe.getUnsafe(); protected final Field field;
protected final long fieldOffset;
protected final boolean isFinal; UnsafeFieldAccessorImpl(Field field) {
this.field = field;
if (Modifier.isStatic(field.getModifiers()))
fieldOffset = unsafe.staticFieldOffset(field);
else
fieldOffset = unsafe.objectFieldOffset(field);
isFinal = Modifier.isFinal(field.getModifiers());
}
// 省略其他方法
}

这里可以做个小结,属性反射操作FieldsetXXgetXX方法最终委托到jdk.internal.misc.UnsafeputXXgetXX方法,而属性的内存偏移地址是通过jdk.internal.misc.UnsafestaticFieldBase()staticFieldOffsetobjectFieldOffset几个方法计算的。

处理构造器调用的底层实现

Constructor#newInstance()方法调用依赖到ConstructorAccessor

    public T newInstance(Object ... initargs)
throws InstantiationException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException
{
if (!override) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, clazz, modifiers);
}
if ((clazz.getModifiers() & Modifier.ENUM) != 0)
throw new IllegalArgumentException("Cannot reflectively create enum objects");
ConstructorAccessor ca = constructorAccessor; // read volatile
if (ca == null) {
ca = acquireConstructorAccessor();
}
@SuppressWarnings("unchecked")
T inst = (T) ca.newInstance(initargs);
return inst;
} // ConstructorAccessor接口
public interface ConstructorAccessor {
/** Matches specification in {@link java.lang.reflect.Constructor} */
public Object newInstance(Object[] args)
throws InstantiationException,
IllegalArgumentException,
InvocationTargetException;
}

而获取ConstructorAccessor实例也是通过反射工厂类ReflectionFactory,具体是ReflectionFactory#newConstructorAccessor

    public ConstructorAccessor newConstructorAccessor(Constructor<?> c) {
checkInitted();
Class<?> declaringClass = c.getDeclaringClass();
// 抽象方法会进入此if分支
if (Modifier.isAbstract(declaringClass.getModifiers())) {
return new InstantiationExceptionConstructorAccessorImpl(null);
}
// 宿主类直接是Class类型,则无法实例化
if (declaringClass == Class.class) {
return new InstantiationExceptionConstructorAccessorImpl
("Can not instantiate java.lang.Class");
} // use the root Constructor that will not cache caller class
Constructor<?> root = langReflectAccess.getRoot(c);
if (root != null) {
c = root;
} // 当前声明构造的宿主类是ConstructorAccessorImpl的子类
if (Reflection.isSubclassOf(declaringClass,
ConstructorAccessorImpl.class)) {
return new BootstrapConstructorAccessorImpl(c);
}
//
if (noInflation && !ReflectUtil.isVMAnonymousClass(c.getDeclaringClass())) {
return new MethodAccessorGenerator().
generateConstructor(c.getDeclaringClass(),
c.getParameterTypes(),
c.getExceptionTypes(),
c.getModifiers());
} else {
NativeConstructorAccessorImpl acc =
new NativeConstructorAccessorImpl(c);
DelegatingConstructorAccessorImpl res =
new DelegatingConstructorAccessorImpl(acc);
acc.setParent(res);
return res;
}
}

可见最终得到的ConstructorAccessor实例为DelegatingConstructorAccessorImpl,而DelegatingConstructorAccessorImpl只是一个委托实现,底层是调用NativeConstructorAccessorImpl

class NativeConstructorAccessorImpl extends ConstructorAccessorImpl {
private final Constructor<?> c;
private DelegatingConstructorAccessorImpl parent;
private int numInvocations; NativeConstructorAccessorImpl(Constructor<?> c) {
this.c = c;
} public Object newInstance(Object[] args)
throws InstantiationException,
IllegalArgumentException,
InvocationTargetException
{
// We can't inflate a constructor belonging to a vm-anonymous class
// because that kind of class can't be referred to by name, hence can't
// be found from the generated bytecode.
if (++numInvocations > ReflectionFactory.inflationThreshold()
&& !ReflectUtil.isVMAnonymousClass(c.getDeclaringClass())) {
ConstructorAccessorImpl acc = (ConstructorAccessorImpl)
new MethodAccessorGenerator().
generateConstructor(c.getDeclaringClass(),
c.getParameterTypes(),
c.getExceptionTypes(),
c.getModifiers());
parent.setDelegate(acc);
} return newInstance0(c, args);
} void setParent(DelegatingConstructorAccessorImpl parent) {
this.parent = parent;
}
// 这个就是最终构造实例化对象的native方法
private static native Object newInstance0(Constructor<?> c, Object[] args)
throws InstantiationException,
IllegalArgumentException,
InvocationTargetException;
}

NativeConstructorAccessorImpl#newInstance0()就是最终构造实例化对象的Native方法。当然有例外的情况,例如非正常调用下,如果构造器的宿主类是一个抽象类,那么最终会返回一个InstantiationExceptionConstructorAccessorImpl实例,里面直接抛出InstantiationException异常。

处理方法调用的底层实现

Method#invoke()调用依赖于MethodAccessor

// MethodAccessor接口
public interface MethodAccessor {
/** Matches specification in {@link java.lang.reflect.Method} */
public Object invoke(Object obj, Object[] args)
throws IllegalArgumentException, InvocationTargetException;
} public Object invoke(Object obj, Object... args)
throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException{
if (!override) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz,
Modifier.isStatic(modifiers) ? null : obj.getClass(),
modifiers);
}
MethodAccessor ma = methodAccessor; // read volatile
if (ma == null) {
ma = acquireMethodAccessor();
}
return ma.invoke(obj, args);
}

获取MethodAccessor实例的逻辑和前两节类似,是通过ReflectionFactory#newMethodAccessor()

    public MethodAccessor newMethodAccessor(Method method) {
checkInitted(); if (Reflection.isCallerSensitive(method)) {
Method altMethod = findMethodForReflection(method);
if (altMethod != null) {
method = altMethod;
}
} // use the root Method that will not cache caller class
Method root = langReflectAccess.getRoot(method);
if (root != null) {
method = root;
} if (noInflation && !ReflectUtil.isVMAnonymousClass(method.getDeclaringClass())) {
return new MethodAccessorGenerator().
generateMethod(method.getDeclaringClass(),
method.getName(),
method.getParameterTypes(),
method.getReturnType(),
method.getExceptionTypes(),
method.getModifiers());
} else {
NativeMethodAccessorImpl acc =
new NativeMethodAccessorImpl(method);
DelegatingMethodAccessorImpl res =
new DelegatingMethodAccessorImpl(acc);
acc.setParent(res);
return res;
}
}

最终会委托到NativeMethodAccessorImpl#invoke(Object obj, Object[] args)

class NativeMethodAccessorImpl extends MethodAccessorImpl {
private final Method method;
private DelegatingMethodAccessorImpl parent;
private int numInvocations; NativeMethodAccessorImpl(Method method) {
this.method = method;
} public Object invoke(Object obj, Object[] args)
throws IllegalArgumentException, InvocationTargetException
{
// We can't inflate methods belonging to vm-anonymous classes because
// that kind of class can't be referred to by name, hence can't be
// found from the generated bytecode.
if (++numInvocations > ReflectionFactory.inflationThreshold()
&& !ReflectUtil.isVMAnonymousClass(method.getDeclaringClass())) {
MethodAccessorImpl acc = (MethodAccessorImpl)
new MethodAccessorGenerator().
generateMethod(method.getDeclaringClass(),
method.getName(),
method.getParameterTypes(),
method.getReturnType(),
method.getExceptionTypes(),
method.getModifiers());
parent.setDelegate(acc);
} return invoke0(method, obj, args);
} void setParent(DelegatingMethodAccessorImpl parent) {
this.parent = parent;
} private static native Object invoke0(Method m, Object obj, Object[] args);
}

NativeMethodAccessorImpl#invoke0()就是方法调用的最终调用的Native方法。

小结

学习知识过程总是阶梯式上升的,JDK中的类库设计也类似这样,如果提前熟悉Unsafe类的相关方法,其实反射调用的底层实现也能够相对轻易地理解。属性、构造和方法反射调用底层的实现(只考虑正常调用的情况下)如下:

  • 对于属性(Field):Field#setXX()Field#getXX()分别对应UnsafeputXX()getXX()方法,也就是说完全依赖Unsafe中的Native方法。
  • 对于构造(Constructor):Constructor#newInstance()底层调用NativeConstructorAccessorImpl#newInstance0()
  • 对于方法(Method):Method#invoke()底层调用NativeMethodAccessorImpl#invoke0()

个人博客

(本文完 e-a-20181216 c-1-d)

深入分析Java反射(七)-简述反射调用的底层实现的更多相关文章

  1. 深入分析Java反射(八)-优化反射调用性能

    Java反射的API在JavaSE1.7的时候已经基本完善,但是本文编写的时候使用的是Oracle JDK11,因为JDK11对于sun包下的源码也上传了,可以直接通过IDE查看对应的源码和进行Deb ...

  2. 深入分析Java反射(六)-反射调用异常处理

    前提 Java反射的API在JavaSE1.7的时候已经基本完善,但是本文编写的时候使用的是Oracle JDK11,因为JDK11对于sun包下的源码也上传了,可以直接通过IDE查看对应的源码和进行 ...

  3. Java反射机制demo(七)—反射机制与工厂模式

    Java反射机制demo(七)—反射机制与工厂模式 工厂模式 简介 工厂模式是最常用的实例化对象模式. 工厂模式的主要作用就是使用工厂方法代替new操作. 为什么要使用工厂模式?直接new不好吗? 直 ...

  4. 深入分析Java反射(五)-类实例化和类加载

    前提 其实在前面写过的<深入分析Java反射(一)-核心类库和方法>已经介绍过通过类名或者java.lang.Class实例去实例化一个对象,在<浅析Java中的资源加载>中也 ...

  5. 深入分析Java反射(四)-动态代理

    动态代理的简介 Java动态代理机制的出现,使得Java开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类.代理类会负责将所有的方法调用分派到委托对象上反射执行,在分 ...

  6. 反射工具类.提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class,被AOP过的真实类等工具函数.java

    import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.Validate; import org.ap ...

  7. Java基础:(七)反射

    一.什么是反射 理解反射之前,先要搞懂一件事情,类加载到底是怎么一回事? 类加载相当于Class对象的加载.每个类都有一个Class对象,包含了与类有关的信息.当编译一个新类时,会产生一个同名的.cl ...

  8. Java反射学习-4 - 反射调用方法

    反射调用方法: package cn.tx.reflect; import java.lang.reflect.Constructor; import java.lang.reflect.Method ...

  9. 深入分析Java反射(一)-核心类库和方法

    前提 Java反射的API在JavaSE1.7的时候已经基本完善,但是本文编写的时候使用的是Oracle JDK11,因为JDK11对于sun包下的源码也上传了,可以直接通过IDE查看对应的源码和进行 ...

随机推荐

  1. 【docker】docker持续集成CI/持续部署CD

    持续集成(CI) 持续集成(Continuous integration)是一种流行的软件开发实践.集成是指开发将自己本地的代码提交到git等远端仓库上,那么持续集成就是每天多次提交,提早提交代码. ...

  2. 端口通不通 telnet wget ssh

    如何测试端口通不通(四种方法) 投稿:mrr 一般情况下使用"telnet ip port"判断端口通不通.接下来通过本文给大家分享四种方法测试端口通不通,感兴趣的朋友一起学习吧 ...

  3. [LeetCode] 932. Beautiful Array 漂亮数组

    For some fixed N, an array A is beautiful if it is a permutation of the integers 1, 2, ..., N, such ...

  4. css快速浏览

    meta <meta charset="utf-8" /> <meta name="keywords" content="key1, ...

  5. ActorFramework教程对比及规划

    牢骚太盛防肠断,风物长宜放眼量. 一.引子 昨天的文章,本来就是想写写ActorFramework的教程内容,结果写着写着偏了,变成了吐槽. 首先,声明一下,自己从未参加过任何LabVIEW培训班,也 ...

  6. swoole在线聊天学习笔记

    <?php $http=); $http->on('request',function(swoole_http_request $request,swoole_http_response ...

  7. apache flink源码挖坑 (未完待续)

    Apache Flink 源码解读(一) ​ By yyz940922原创 项目模块 (除去.git, .github, .idea, docs等): flink-annotations: flink ...

  8. NASA的10条编码规则

    关于NASA的10条编程规则,他们曾表示:这些规则的作用就像汽车上的安全带:最初,它们可能有点不舒服,但过了一会儿,它们的使用就变成了第二天性,而没有使用它们就变得不可想象. Gerard J. Ho ...

  9. centos破解压缩文件密码

    rarcrack是linux系统端的一款破解加密压缩包的工具,rarcrack使用的穷举法进行破解已经加密的rar.zip和7z压缩包,支持设置多线程,和文件类型进行破解. 1.rarcrack下载页 ...

  10. Ubantu学习笔记2

    又是新的一天,继续学习Ubantu命令 cat 可以查看文件内容 cat -n p.py 可以在查看文件内容的同时显示行号 cat -s p.py 可以将多行空白的地方进行合并成一行(输入空格的地方不 ...