如何使用ASM判定方法是否重写自指定类,解决泛型擦除导致的描述符匹配失败问题
核心原因
这是Java泛型类型擦除机制生成的桥接方法导致的正常现象:当类实现带泛型参数的Comparable接口时,编译器会自动生成两个compareTo方法:
- 你自己编码实现的、参数为具体
SimpleVersion类型的方法,描述符为compareTo (Lorg/imanity/imanityspigot/CompatibilityPatches$SimpleVersion;)I - 编译器自动生成的桥接方法,参数为类型擦除后的
Object类型,描述符为compareTo (Ljava/lang/Object;)I,内部会做参数类型转换后调用你实现的具体方法,用于兼容泛型擦除后的调用逻辑。
你当前的校验逻辑直接比对描述符,自然会出现匹配失败的问题。
可行解决方案
你可以根据你的校验场景选择以下任意一种方案调整匹配逻辑:
- 方案1:识别桥接方法标记,匹配实际实现方法
ASM的MethodNode的access字段携带了方法的标记位,你可以通过Opcodes.ACC_BRIDGE(值为0x40)过滤掉编译器生成的桥接方法,只比对非桥接的业务实现方法即可。
示例判断逻辑:boolean isBridgeMethod = (methodNode.access & Opcodes.ACC_BRIDGE) != 0; - 方案2:比对泛型签名(Signature)而非类型擦除后的描述符(Desc)
如果编译时保留了泛型元数据,MethodNode的signature字段会存储带泛型参数的完整方法签名,不会受类型擦除影响。你可以调整校验逻辑为比对方法名+签名,即可直接匹配到对应的重写实现。 - 方案3:实现符合JLS规范的重写判定逻辑
你可以按照Java语言规范的方法重写规则自行实现判定逻辑:只要方法名相同、子类方法的参数类型擦除后和父类方法参数类型一致、返回值兼容、修饰符符合重写权限要求,即可判定为重写实现,不需要完全要求描述符完全一致。
内容的提问来源于stack exchange,提问作者LeeGod
相关产品推荐
相关产品推荐

