动态代理不是反射生成的,而是proxy类调用proxygenerator拼装字节码、classloader加载、jvm实例化;反射仅用于后续方法调用与元数据读取。

Java 反射生成动态代理类的底层原理,不是靠“反射生成字节码”,而是反射参与调用、Proxy 负责生成、ClassLoader 完成加载、JVM 执行实例化。想真正学懂,关键不在死记 API,而在理清四层协作关系:谁触发、谁生成、谁加载、谁运行。
动态代理不是反射生成的,是 Proxy 配合 JVM 生成的
很多人误以为 Proxy.newProxyInstance 是靠反射写出来的 class 文件,其实不是:
-
java.lang.reflect.Proxy是一个工具类,它本身不生成字节码; - 真正干活的是内部私有类
ProxyGenerator(JDK 内部 API),它按固定模板拼装 JVM 字节码指令(比如aload_0、invokeinterface); - 这个过程不依赖编译器、不解析 Java 源码、也不走 javac,而是硬编码逻辑 + 接口方法遍历 → 逐个生成
invoke()转发桩; - 你可以加这行代码导出生成的 class 文件,反编译后就能看到
$Proxy0的真实结构:System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
学习路径要分三步走:先看调用链,再拆字节码,最后动手验证
-
第一步:跟踪
newProxyInstance的完整流程- 输入:ClassLoader、接口数组、InvocationHandler 实例
- 校验接口合法性(public、非类、可被当前 ClassLoader 加载)
- 生成唯一类名(如
$Proxy0),查缓存 → 命中则复用,否则生成 - 调用
ProxyGenerator.generateProxyClass(...)得到byte[] - 用
defineClass加载为Class>,再用构造器创建实例
-
第二步:理解生成的字节码干了什么
- 代理类继承
Proxy,实现所有传入接口 - 每个接口方法都对应一段固定逻辑:查 method cache → 调
h.invoke(this, mX, args) - 构造器只做一件事:把
InvocationHandler传给父类Proxy的 protected 构造器 - 所有字段(如
m1,m2)都是 static Method,由ProxyGenerator在生成时预设并初始化
- 代理类继承
-
第三步:自己动手验证关键点
- 写一个空接口 + 空实现类,用
Proxy.newProxyInstance创建代理 - 开启保存 class 文件,用 JAD 或 jclasslib 查看
$Proxy0结构 - 对比
getDeclaredMethods()返回的方法列表和实际.class中的方法签名是否一致 - 尝试传入非法接口(比如非 public 接口),观察抛出
IllegalArgumentException的位置
- 写一个空接口 + 空实现类,用
注意反射在其中的真实角色
反射在这里不是“生成者”,而是“执行者”和“桥梁”:
-
Method.invoke()被用来调用用户写的InvocationHandler.invoke(),这是反射最典型的用途 -
Constructor.newInstance()用于实例化生成的代理类,也是反射调用 -
Class.getMethod()等用于获取目标方法供InvocationHandler转发,属于元数据读取环节 - 但整个代理类的定义、字节码拼装、类加载,全部绕开反射,走的是 JVM 底层机制(
Unsafe或MethodHandles)
不复杂但容易忽略。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











