原理:每个类加载后在方法区有对应的 Class 对象,记录字段、方法、构造器的元数据;反射通过这些元数据动态查询和调用——Method.invoke 最终经 JVM 的 native 桥接执行目标方法。慢的来源:1)每次调用做可见性/访问权限检查;2)参数要装箱成 Object[],返回值要拆箱,存在内存分配;3)JIT 难以内联——调用目标是运行期才确定的,编译器无法做内联与后续优化,这是与直接调用的本质差距;4)native 与 Java 栈之间的切换开销。
优化手段:1)缓存反射对象——Class.forName、getMethod 的查找很贵,Method/Field 对象应缓存复用;2)setAccessible(true) 跳过访问检查(注意模块系统的限制);3)MethodHandle(invokedynamic 体系)——更接近 JVM 内部的调用表示,权限检查在创建时一次性完成,性能好且 JIT 友好;4)LambdaMetafactory 把反射调用转成方法句柄再转 lambda 调用,接近直接调用(MapStruct 之外的映射框架常用);5)彻底方案是编译期生成代码(注解处理器、字节码增强)。追问方向:JDK 的 Inflation 机制(反射调用超过阈值后由 native 实现切换为生成的字节码实现)、反射对 GC 与元空间的影响。
(约 440 字)