You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用ASM字节码生成编解码器时遇类方法找不到问题求助

问题排查与解决方案

核心原因:泛型类型擦除导致方法签名不匹配

你的Patchable<T>是泛型类,Java编译时会执行类型擦除:泛型参数T会被替换为上限类型(此处为Object),因此编译后的Patchable类中,getPayload()方法的实际签名是:

public Object getPayload()

但ASM生成的字节码里直接调用了签名为()Ljava/lang/String;的getPayload()方法:

INVOKEVIRTUAL com/cinnober/msgcodec/Patchable.getPayload ()Ljava/lang/String;

JVM加载生成的Codec类时,会在Patchable类中查找该签名的方法,而实际类中只有()Ljava/lang/Object;版本的方法,因此抛出NoSuchMethodError。

CHECKCAST指令仅验证对象是Patchable实例,和方法签名是否匹配无关。

修复方案

调整ASM生成的字节码逻辑,先调用泛型擦除后的getPayload()(返回Object),再做类型转换到目标类型,最后调用写入方法:

修改后的ASM指令序列:

ALOAD 1
ALOAD 0
GETFIELD com/cinnober/msgcodec/blink/GeneratedBlinkCodec0.accessor_PatchableEntity_patchable : Lcom/cinnober/msgcodec/Accessor;
ALOAD 2
INVOKEINTERFACE com/cinnober/msgcodec/Accessor.getValue (Ljava/lang/Object;)Ljava/lang/Object; (itf)
CHECKCAST com/cinnober/msgcodec/Patchable
INVOKEVIRTUAL com/cinnober/msgcodec/Patchable.getPayload ()Ljava/lang/Object;
CHECKCAST java/lang/String
INVOKESTATIC com/cinnober/msgcodec/blink/BlinkOutput.writeStringUTF8Null (Lcom/cinnober/msgcodec/io/ByteSink;Ljava/lang/String;)V
RETURN

关键修改点

  • 将INVOKEVIRTUAL的方法签名从()Ljava/lang/String;改为()Ljava/lang/Object;,匹配泛型擦除后的实际方法
  • 添加CHECKCAST java/lang/String指令,将返回的Object转换为String类型,适配后续写入方法的参数要求

额外验证建议

  • 执行javap -c com.cinnober.msgcodec.Patchable命令查看编译后的Patchable类字节码,确认getPayload()的实际签名,验证上述结论
  • 若后续支持其他类型的Patchable<T>,只需将CHECKCAST的类型替换为对应类型即可,保持逻辑一致性

内容的提问来源于stack exchange,提问作者Erik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 14:38:18