反射的性能影响与优化建议?
请分析Java反射机制的性能开销来源,包括动态类型检查、方法查找、访问控制检查、装箱拆箱等。说明如何优化反射性能,以及setAccessible(true)的作用。对比MethodHandle和反射的差异。
回答
孤独的心
性能开销来源:
- 方法查找:获取Method对象需要扫描类的方法表
- 访问控制检查:每次invoke检查调用权限
- 自动装箱:基本类型参数需要装箱
- 可变参数:invoke(Object...)创建数组
- JIT无法内联:反射调用难以被JIT优化
测试数据:反射调用比直接调用慢约10-100倍(但实际应用中差异可接受)。
优化建议:
- 缓存Method/Field对象:不要反复getMethod(),将Method对象缓存为静态变量
- setAccessible(true):跳过访问控制检查,提升性能(约20-30%)
- 使用基本类型方法:Method.invoke(null, int)有特定版本
反射 vs MethodHandle(Java 7引入):
- MethodHandle更轻量,类似于函数指针
- MethodHandle.findXxx比反射慢,但invoke比反射快
- MethodHandle可以被JIT内联优化
- MethodHandle不能绕过访问控制(除非lookup有权限)
最佳实践:只在框架层面的通用代码中使用反射;业务代码尽量避免。