GeneratedMethodAccessor如何实现对Java私有方法的访问?
当通过反射调用私有方法时,GeneratedMethodAccessor类并不会受常规的Java访问修饰符规则限制,但这有个关键前提:你必须先通过Method.setAccessible(true)完成权限绕过的声明。具体细节如下:
前置权限声明是必要条件
在尝试调用私有方法前,必须调用method.setAccessible(true),这一步会修改方法内部的访问标志,告知JVM允许跳过访问权限检查。如果省略这一步,哪怕JVM试图生成GeneratedMethodAccessor类,最终调用时依然会抛出IllegalAccessException——因为JVM不会允许未授权的私有方法访问。GeneratedMethodAccessor的特殊处理
当你第一次调用已开启setAccessible的私有方法时,JVM会动态生成GeneratedMethodAccessorXXX类。这个类的字节码中直接包含了对目标私有方法的调用指令,并且JVM在执行该类的代码时会跳过常规的访问权限校验。这是JVM为了反射性能优化专门做的“后门”——因为GeneratedMethodAccessor属于JVM信任的系统生成类,不受普通类的访问规则约束。实际运行示例
以下代码可以验证这个行为:class PrivateMethodDemo { private void sayPrivate() { System.out.println("私有方法执行了"); } public static void main(String[] args) throws Exception { Method privateMethod = PrivateMethodDemo.class.getDeclaredMethod("sayPrivate"); // 必须开启权限绕过 privateMethod.setAccessible(true); // 第一次调用触发GeneratedMethodAccessor生成 privateMethod.invoke(new PrivateMethodDemo()); // 后续调用直接使用生成的代理类,性能更高 privateMethod.invoke(new PrivateMethodDemo()); } }运行这段代码会正常输出两次“私有方法执行了”,不会触发访问权限异常。
核心本质
GeneratedMethodAccessor的存在是为了优化反射调用的性能,它本质上是JVM将反射调用转化为直接方法调用的一种手段。而对于私有方法的访问,JVM已经通过setAccessible的前置操作确认了合法性,因此生成的代理类可以直接执行调用,无需再做访问检查。
内容的提问来源于stack exchange,提问作者choxsword

