我想知道是否有任何额外的优化我可以实现以提高Java中反射调用的速度.并不是说性能是令人望而却步的,但是我在考虑库中的某些代码时得到了一些我正在编写的代码在某个地方以紧密的方式实现.
考虑一种反射性调用的实用方法:
public static Object invoke(Object targetObject, String methodName, Object[] arguments, Class>[] signature)
基本操作是
return method.invoke(targetObject, arguments);
作为性能优化,我使用目标对象的类,方法名称和签名(其代码可能使用某些改进)的哈希来缓存方法,但除此之外,还有什么我可以做的吗?我听说过InvokeDynamic的一些早期实现的参考听起来很有希望,但我只是假设它们可能还不适用,并且我打算使用自己的字节代码操作,因为我希望保持实用程序简单(但速度快).
干杯.
以下评论与Sun的实施有关,特别是OpenJDK 6.您的里程可能因其他Java平台实施而异.
java.lang.Class
做一些缓存本身,所以实现自己的缓存可能不会改善很多东西.使用和不使用手动缓存进行计时测试.
实际的调用机制也得到了优化.使用JNI调用反射方法的前15次运行(默认情况下); 之后,生成字节码并调用反射方法将直接在Java代码中调用该方法执行相同的操作.
我围绕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业务并没有在反射加速/消除的基础上吸引太多的开发人员.
谢谢克里斯.