桥接方法是编译器为保障泛型擦除后JVM多态正确分派而自动生成的转发桩,标记为ACC_BRIDGE和ACC_SYNTHETIC,通过强制类型转换调用实际方法,确保vtable填充与重写语义成立。

要真正理解 JVM 如何在泛型擦除后仍保障多态正确分派,关键不是看源码,而是直击字节码——桥接方法就藏在那里,不声不响地撑起整个泛型多态的底层契约。
用 javap 看清桥接方法的真实存在
编译一个泛型接口实现类(如 UserInfoOperator implements Operator<string></string>)后,执行:
javap -v UserInfoOperator.class
在输出的方法列表中,找同时带有 ACC_BRIDGE 和 ACC_SYNTHETIC 标志的方法。例如:
public void process(java.lang.Object);<br>flags: ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
它没有 LineNumberTable,局部变量表为空,也不带任何注解——这些正是编译器生成、非人工编写的方法特征。
桥接方法为什么必须存在
JVM 方法分派只认签名:方法名 + 参数类型 + 返回类型,完全无视泛型。而泛型擦除后,父类/接口方法签名已“降级”:
- 接口定义:
void process(T t)→ 擦除为void process(Object t) - 子类实现:
void process(String s)→ 擦除后仍是void process(String s)
二者参数类型不同(Object vs String),JVM 判定这不是重写,而是重载——多态链就此断裂。桥接方法就是补上这个缺口的转发桩:
public void process(Object obj) { this.process((String) obj); }
它让 JVM 看到一个“签名完全匹配父类擦除后声明”的方法,从而顺利填入子类的 vtable,确保向上转型调用也能路由到子类逻辑。
反射与工具链中必须识别桥接方法
很多问题源于把桥接方法当成普通业务方法处理:
- 用
getDeclaredMethods()遍历时,会多出一个看似重复的process(Object) - Spring AOP 或 MyBatis 动态代理若未过滤桥接方法,可能报
IllegalArgumentException: object is not an instance of declaring class - 序列化框架或 JSON 反序列化时,若按方法签名匹配 setter,可能误选桥接入口
正确做法是:调用 Method.isBridge() 判断;不要依赖方法名或参数类型做人工匹配——协变返回、通配符等场景下极易误判。
删掉桥接方法会发生什么
桥接方法不可删除,否则 JVM 多态机制直接失效:
- 父类引用调用泛型方法时抛
AbstractMethodError - 反射
invoke()时因找不到 public 入口而失败 - Lombok 的
@Delegate在泛型类中可能生成错误桥接逻辑,导致运行时行为异常
它的作用不是“辅助”,而是 JVM 方法重写语义成立的必要条件——它是编译器为向后兼容所写的底层 glue code。

















