Java 反射优化
Java About 5,424 words示例代码
public class ReflectOptimizeDemo {
public static void main(String[] args) throws Exception {
Method getInfo = TestObject.class.getMethod("getInfo");
TestObject testObject = TestObject.class.getDeclaredConstructor().newInstance();
// 前 16 次调用,性能较低
// 第 17 次开始,性能变高
for (int i = 0; i < 17; i++) {
System.out.printf("%d\t", i);
getInfo.invoke(testObject);
}
System.in.read();
}
}
public class TestObject {
public String name;
public int age;
public String getInfo() {
System.out.println("getInfo..." + new Exception().getStackTrace()[1].getClassName());
return this.name + "-" + this.age;
}
}
输出:可以看到第17
次,方法调用的对象是GeneratedMethodAccessor1
。
0 getInfo...jdk.internal.reflect.NativeMethodAccessorImpl
1 getInfo...jdk.internal.reflect.NativeMethodAccessorImpl
2 getInfo...jdk.internal.reflect.NativeMethodAccessorImpl
3 getInfo...jdk.internal.reflect.NativeMethodAccessorImpl
4 getInfo...jdk.internal.reflect.NativeMethodAccessorImpl
5 getInfo...jdk.internal.reflect.NativeMethodAccessorImpl
6 getInfo...jdk.internal.reflect.NativeMethodAccessorImpl
7 getInfo...jdk.internal.reflect.NativeMethodAccessorImpl
8 getInfo...jdk.internal.reflect.NativeMethodAccessorImpl
9 getInfo...jdk.internal.reflect.NativeMethodAccessorImpl
10 getInfo...jdk.internal.reflect.NativeMethodAccessorImpl
11 getInfo...jdk.internal.reflect.NativeMethodAccessorImpl
12 getInfo...jdk.internal.reflect.NativeMethodAccessorImpl
13 getInfo...jdk.internal.reflect.NativeMethodAccessorImpl
14 getInfo...jdk.internal.reflect.NativeMethodAccessorImpl
15 getInfo...jdk.internal.reflect.NativeMethodAccessorImpl
16 getInfo...jdk.internal.reflect.GeneratedMethodAccessor1
原理
JDK
中,当反射代码调用超过16
次时(即:第17
时开始,在内存中生成实例对象,加速调用)。
// java.lang.reflect.Method#invoke
public final class Method extends Executable {
@CallerSensitive
@ForceInline // to ensure Reflection.getCallerClass optimization
@HotSpotIntrinsicCandidate
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);
}
}
当numInvocations
大于了ReflectionFactory.inflationThreshold()
阈值(可以忽略后面的isVMAnonymousClass
判断条件),开始生成访问类。
具体生成的方法在jdk.internal.reflect.MethodAccessorGenerator#generate
中。
// jdk.internal.reflect.NativeMethodAccessorImpl#invoke
class NativeMethodAccessorImpl extends MethodAccessorImpl {
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);
}
}
主要方法
Method
类中的invoke()
方法。
NativeMethodAccessorImpl
类中的invoke()
方法。
ReflectionFactory
类中的inflationThreshold()
、checkInitted()
方法。
优化开关
设置直接生成实例对象,如果设置为false
,则直接生成实例对象。
-Dsun.reflect.noInflation=true
设置膨胀阈值,默认15
(循环从0-15
,共16
次)
-Dsun.reflect.inflationThreshold=10
源码
// jdk.internal.reflect.ReflectionFactory#checkInitted
public class ReflectionFactory {
private static void checkInitted() {
if (initted) return;
// Defer initialization until module system is initialized so as
// to avoid inflation and spinning bytecode in unnamed modules
// during early startup.
if (!VM.isModuleSystemInited()) {
return;
}
Properties props = GetPropertyAction.privilegedGetProperties();
String val = props.getProperty("sun.reflect.noInflation");
if (val != null && val.equals("true")) {
noInflation = true;
}
val = props.getProperty("sun.reflect.inflationThreshold");
if (val != null) {
try {
inflationThreshold = Integer.parseInt(val);
} catch (NumberFormatException e) {
throw new RuntimeException("Unable to parse property sun.reflect.inflationThreshold", e);
}
}
disableSerialConstructorChecks =
"true".equals(props.getProperty("jdk.disableSerialConstructorChecks"));
initted = true;
}
}
Views: 1,068 · Posted: 2023-06-02
————        END        ————
Give me a Star, Thanks:)
https://github.com/fendoudebb/LiteNote扫描下方二维码关注公众号和小程序↓↓↓
Loading...