java reflection.

Method.invoke

调用链

method.invoke()
->
MethodAccessor.invoke()
-> ReflectionFactory.newMethodAccessor() -> DelegatingMethodAccessorImpl
-> invoke
-> DelegatingMethodAccessorImpl.invoke
-- delegate = NativeMethodAccessorImpl
-> invoke
if(numInvocations > ReflectionFactory.inflationThreshold())
-> acc = MethodAccessorGenerator.generateMethod
-> parent.setDelegate(acc)
invoke0()//native invoke
-- deletegate = sun.reflect.GeneratedMethodAccessor1@101df177

补充说明

  • 下文中代理类皆为MethodAccessor的子类

  • ReflectionFactory.noInflation = true 会直接生成代理类

  • 反射调用方法执行次数大于ReflectionFactory.inflationThreshold(默认15)时,会生成代理类,用于提高反射执行效率,代理类反编译后源码大致如下(以String#toCharArray为例)

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package sun.reflect;

import java.lang.reflect.InvocationTargetException;

public class GeneratedMethodAccessor1 extends MethodAccessorImpl {
public GeneratedMethodAccessor1() {
}

//var1 为原object对象,var为方法参数数组
public Object invoke(Object var1, Object[] var2) throws InvocationTargetException {
if (var1 == null) {
throw new NullPointerException();
} else {
//生成字节码时已经自动处理了对象类型
String var10000;
try {
var10000 = (String)var1;
if (var2 != null && var2.length != 0) {
throw new IllegalArgumentException();
}
} catch (NullPointerException | ClassCastException var4) {
throw new IllegalArgumentException(var4.toString());
}

try {
//实际调用 等价于 strObj.toCharArray();所以开销很小
return var10000.toCharArray();
} catch (Throwable var3) {
throw new InvocationTargetException(var3);
}
}
}
}

  • 当系统中反射调用过多时会导致metaspace溢出,因为生成了过多的代理类

  • noInflation可通过sun.reflect.noInflation配置

  • inflationThreshold可通过sun.reflect.inflationThreshold配置

Constructor.newInstance

调用链

和上文大致类似

补充说明

  • 生成代理类的代理类反编译后源码大致如下(以new String(String)为例)
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package sun.reflect;

import java.lang.reflect.InvocationTargetException;

public class GeneratedConstructorAccessor2 extends ConstructorAccessorImpl {
public GeneratedConstructorAccessor2() {
}

public Object newInstance(Object[] var1) throws InvocationTargetException {
String var10000;
String var10001;
String var10002;
try {
var10000 = new String;
var10001 = var10000;
if (var1.length != 1) {
throw new IllegalArgumentException();
}

var10002 = (String)var1[0];
} catch (NullPointerException | ClassCastException var3) {
throw new IllegalArgumentException(var3.toString());
}

try {
var10001.<init>(var10002);
return var10000;
} catch (Throwable var2) {
throw new InvocationTargetException(var2);
}
}
}