有什么方法可以进一步优化Java反射方法调用?

2022-09-01 16:33:52

我想知道我是否可以实现任何其他优化来提高Java中反射调用的速度。并不是说性能令人望而却步,但是当想到我正在编写的库中的某个代码片段在某个地方的紧密循环中实现时,我得到了一些想法。

考虑一个实用工具方法来反射性地调用:

public static Object invoke(Object targetObject, String methodName, Object[] arguments, Class<?>[] signature)

基本操作是

return method.invoke(targetObject, arguments);

作为性能优化,我使用目标对象的类,方法名称和签名的哈希值(其代码可能需要一些改进)来缓存方法,但除此之外,我还能做些什么吗?我听说过一些听起来很有前途的 InvokeDynamic 早期实现,但我只是假设它们可能还不适用,并且我忽略了我自己的字节代码操作,因为我想保持实用程序简单(但快速)。

干杯。


答案 1

下面的评论与Sun的实现有关,特别是OpenJDK 6。您的里程可能因其他 Java 平台实现而异。

java.lang.Class本身会做一些缓存,所以实现自己的缓存可能不会有太大的改善。使用和不使用手动缓存进行计时测试。

实际的调用机制也得到了优化。反射方法的前 15 次运行(缺省情况下)使用 JNI 调用;之后,将生成字节码,并且调用该反射方法将执行与在Java代码中直接调用该方法相同的操作。


答案 2

我围绕Chris Jester-Young的答案进行了一些测试,并使用详细选项,我肯定观察到编译器在第15次调用时采取了一些行动。如果没有更复杂的测试,很难说是否有很多性能差异,但它是有说服力的。下面是输出:

Test# 0
Test# 1
Test# 2
Test# 3
Test# 4
Test# 5
Test# 6
Test# 7
Test# 8
Test# 9
Test# 10
Test# 11
Test# 12
Test# 13
Test# 14
[Loaded sun.reflect.ClassFileConstants from C:\jdk1.5.0_06\jre\lib\rt.jar]
[Loaded sun.reflect.AccessorGenerator from C:\jdk1.5.0_06\jre\lib\rt.jar]
[Loaded sun.reflect.MethodAccessorGenerator from C:\jdk1.5.0_06\jre\lib\rt.jar]
[Loaded sun.reflect.ByteVectorFactory from C:\jdk1.5.0_06\jre\lib\rt.jar]
[Loaded sun.reflect.ByteVector from C:\jdk1.5.0_06\jre\lib\rt.jar]
[Loaded sun.reflect.ByteVectorImpl from C:\jdk1.5.0_06\jre\lib\rt.jar]
[Loaded sun.reflect.ClassFileAssembler from C:\jdk1.5.0_06\jre\lib\rt.jar]
[Loaded sun.reflect.UTF8 from C:\jdk1.5.0_06\jre\lib\rt.jar]
[Loaded java.lang.Void from C:\jdk1.5.0_06\jre\lib\rt.jar]
[Loaded sun.reflect.Label from C:\jdk1.5.0_06\jre\lib\rt.jar]
[Loaded sun.reflect.Label$PatchInfo from C:\jdk1.5.0_06\jre\lib\rt.jar]
[Loaded java.util.AbstractList$Itr from C:\jdk1.5.0_06\jre\lib\rt.jar]
[Loaded sun.reflect.MethodAccessorGenerator$1 from C:\jdk1.5.0_06\jre\lib\rt.jar]
[Loaded sun.reflect.ClassDefiner from C:\jdk1.5.0_06\jre\lib\rt.jar]
[Loaded sun.reflect.ClassDefiner$1 from C:\jdk1.5.0_06\jre\lib\rt.jar]
[Loaded sun.reflect.GeneratedMethodAccessor1 from __JVM_DefineClass__]
Test# 15
Test# 16
Test# 17

我猜 InvokeDynamic 业务并没有在反射加速/消除的基础上吸引太多开发人员。

谢谢克里斯。


推荐