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

使用ASM+Javaagent插栈映射帧报Type is not assignable to uninitializedThis如何解决

问题1:Current Frame和Stackmap Frame的具体含义是什么,二者有什么区别?

  • Stackmap Frame是类文件StackMapTable属性中预先声明的、对应某一字节码偏移(BCI)位置的局部变量表、操作数栈状态,属于提前写入类文件的元信息,作用是让JVM字节码校验器无需逐行推导全方法的状态,大幅加快校验速度。
  • Current Frame是字节码校验器按照代码执行流,逐指令推导出来的、执行到某一BCI位置时实际的局部变量表、操作数栈状态。
    二者核心区别:Stackmap Frame是插桩时预先声明的预期状态,Current Frame是校验器实际推演得到的真实状态,当真实状态无法赋值给预期声明的状态时,就会抛出你遇到的栈映射不匹配错误。

问题2:为什么@9位置的栈映射帧中存在uninitializedThis?我理解构造方法调用完成前对象一直是uninitializedThis状态,是否正确?

你的理解部分正确:构造方法中,在调用父类构造方法的invokespecial指令执行之前,this的类型确实是特殊的uninitializedThis类型;执行完invokespecial指令后,this就会变成当前类的实际类型,不再是uninitializedThis。
@9位置是异常处理器的入口,你的异常表配置的捕获范围是[0,6],这个范围包含了invokespecial执行前、执行中、执行后的所有代码:

  • 如果异常在invokespecial执行前抛出,进入@9时局部变量0是uninitializedThis
  • 如果异常在invokespecial执行后抛出,进入@9时局部变量0是org/joda/time/TestAllPackages类型
    JVM要求异常处理器的栈映射帧必须兼容所有可能进入该处理器的执行路径的状态,所以校验器推导的预期帧里局部变量0是uninitializedThis,但你插桩时写的帧默认沿用了invokespecial执行后的局部变量状态,导致不匹配。

问题3:我该如何避免该类型与uninitializedThis的不一致问题?

问题根源是你把构造方法invokespecial前后两段状态不兼容的代码,放在了同一个异常捕获块中,导致异常处理器的帧无法同时兼容两种状态,有两种可行方案:

方案1:跳过构造方法插桩

如果不需要监控构造方法的异常,在MyClassVisitor的visitMethod方法中增加过滤逻辑即可:

if (!isNative && !isEnum && !isAbstract && !"<clinit>".equals(name) && !"<init>".equals(name)){
    mv = new MyMethodVisitor(mv, name, access, desc, slashClassName, isStatic, isPublic);
}

方案2:拆分构造方法的异常捕获范围

如果需要监控构造方法的异常,需要把构造方法的代码拆成两个捕获块:

  1. 从方法开始到invokespecial指令前为第一个捕获块,对应的异常处理器帧局部变量0声明为UNINITIALIZED_THIS
  2. 从invokespecial指令后到方法结束为第二个捕获块,对应的异常处理器帧局部变量0声明为当前类的类型
    同时注意,异常处理器的栈映射帧不能使用F_SAME/F_SAME1这类相对前序代码的帧类型,要使用F_NEW全量声明局部变量和操作数栈的内容,构造方法场景的示例代码如下:
// catchStart位置的帧处理
mv.visitFrame(F_NEW, 2, new Object[]{Opcodes.UNINITIALIZED_THIS, "java/lang/String"}, 1, new Object[]{"java/lang/Throwable"});

另外你代码中注释的疑问“为什么tryEnd后的visitFrame不能省略”:因为goto属于跳转指令,跳转指令的下一个字节码位置是新基本块的入口,必须显式声明栈映射帧,否则校验器无法推导该位置的状态。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 03:48:02