前提
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.Unsafe
的putObject(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());
}
// 省略其他方法
}
這里可以做個小結,屬性反射操作Field
的setXX
和getXX
方法最終委托到jdk.internal.misc.Unsafe
的putXX
和getXX
方法,而屬性的內存偏移地址是通過jdk.internal.misc.Unsafe
的staticFieldBase()
、staticFieldOffset
和objectFieldOffset
幾個方法計算的。
處理構造器調用的底層實現
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()
分別對應Unsafe
的putXX()
和getXX()
方法,也就是說完全依賴Unsafe
中的Native方法。 - 對於構造(Constructor):
Constructor#newInstance()
底層調用NativeConstructorAccessorImpl#newInstance0()
。 - 對於方法(Method):
Method#invoke()
底層調用NativeMethodAccessorImpl#invoke0()
個人博客
(本文完 e-a-20181216 c-1-d)
技術公眾號(《Throwable文摘》),不定期推送筆者原創技術文章(絕不抄襲或者轉載):
娛樂公眾號(《天天沙雕》),甄選奇趣沙雕圖文和視頻不定期推送,緩解生活工作壓力: