0
点赞
收藏
分享

微信扫一扫

JAVA系列: Java的反射性能问题

木匠0819 2022-03-12 阅读 53


目录

性能问题

原因 

1.产生了Dynamic Resolve 

2.安全性验证 

3.影响运行时优化 

处理方法 

1.使用Cache 

2.使用MethodHandle类 

3.使用Runtime创建的类 

性能问题

调用Java的反射API是有较高的性能开销的


Class class1 = Class.forName("com.xxx.TestReflect");

TestReflect tr = (TestReflect) class1.newInstance();

Method method = class1.getDeclaredMethod("mPrivate");

method.setAccessible(true);


通过反射访问、修改类的属性和方法时会远慢于直接操作,但性能问题的严重程度取决于在程序中是如何使用反射的。如果使用得很少,不是很频繁,性能将不会是什么问题;


原因 

纠其原因,性能的开销主要在两方面: 

1.产生了Dynamic Resolve 


无论是通过字符串获取Class、Method还是Field,都需要JVM的动态链接机制动态的进行解析和匹配,势必造成性能开销。 



2.安全性验证 


每一次的反射调用都会造成Java安全机制进行额外的安全性验证,造成性能开销。 



3.影响运行时优化 


反射代码使得许多JVM的运行时优化无法进行。 



处理方法 

1.使用Cache 


针对上述原因1: 对通过反射调用获得的Class、Method、Field实例进行缓存,避免多次Dynamic Resolve。 



2.使用MethodHandle类 


针对上述原因2:Java 7开始提供了java.lang.invoke.MethodHandle类,MethodHandle类的安全性验证在获取实例时进行而不是每次调用时都要进行验证,减小开销。 



3.使用Runtime创建的类 


该方法最为强大,可以针对上述原因1、2、3进行全面优化。具体做法为: 


  • 在编译时设计好一个接口,由该接口封装所有的反射调用。
  • 在运行时动态生成一个类实现该接口,该动态生成的类一旦完成define就和普通类没有区别,不需要后续的Dynamic Resolve,没有额外的安全性验证,也不会影响JVM的运行时优化。
  • 该方法不能覆盖反射API的所有Use case,例如某个反射调用需要修改某实例的private字段,是无法动态生成一个合法的类这样去做的。 






举报

相关推荐

0 条评论