bytebuddy 的 elementmatchers.isbridge() 依据 jvm 字节码 acc_bridge 标志精准识别桥接方法,仅适用于 methoddescription,常用于拦截或排除泛型协变等生成的合成方法,不可用于类型或字段匹配。

在 Java 中,使用 ByteBuddy 的 ElementMatchers.isBridge() 可以精准识别并拦截编译器自动生成的桥接方法(bridge methods),但需注意其适用场景和常见陷阱——它只匹配已标记为 ACC_BRIDGE 的方法,且必须结合正确的匹配时机(如在类型加载前对方法进行筛选)。
桥接方法是什么,为什么需要专门拦截
桥接方法是 javac 为支持泛型协变、接口默认方法重写等生成的合成方法,例如:
interface Service<t> { void accept(T t); }
class StringService implements Service<string> { public void accept(String s) { ... } }
</string></t>
编译后,StringService 会额外生成一个桥接方法:public void accept(Object o) { accept((String)o); }
该方法带有 ACC_BRIDGE 和 ACC_SYNTHETIC 标志。ByteBuddy 的 isBridge() 正是依据 JVM 字节码中的 ACC_BRIDGE 标志判断,而非靠方法签名推断。
用 isBridge() 做方法级拦截的正确写法
直接在 method() 条件中使用 isBridge() 即可精准定位桥接方法:
- 拦截所有桥接方法:
method(isBridge()) - 拦截特定名称的桥接方法:
method(named("accept").and(isBridge())) - 排除桥接方法(常用于避免重复增强):
method(not(isBridge()))
注意:不能用 isBridge() 匹配构造器或字段;它仅适用于 MethodDescription。
常见误用与避坑点
-
不要在类匹配阶段用 isBridge():桥接是方法属性,
type(isBridge())永远不成立 -
不能靠参数类型判断是否为桥接:比如
accept(Object)不一定是桥接方法,可能是用户显式定义的,只有带ACC_BRIDGE标志才算 -
动态代理或某些字节码操作库可能清除 ACC_BRIDGE 标志:此时
isBridge()失效,需配合isSynthetic()+ 签名分析辅助判断(但非精准)
完整示例:只为桥接方法添加日志
以下代码仅对桥接方法织入日志,不影响原始业务方法:
new ByteBuddy() .redefine(targetType) .method(isBridge()) .intercept(MethodDelegation.to(BridgeLogger.class)) .make() .load(classLoader, ClassLoadingStrategy.Default.INJECTION);
其中 BridgeLogger 可简单定义为:
public class BridgeLogger {
public static void log(Invocation invocation) {
System.out.println("Bridge method intercepted: " + invocation.getMethod().getName());
}
}
这样既避免了对真实业务方法的干扰,又能精准观测泛型擦除带来的桥接行为。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











