Java ASM生成字节码报错:Bad local variable type (dload) 求助
排查JVM字节码VerifyError(double/long类型局部变量异常)
问题场景
使用Java ASM库生成JVM字节码(开发自定义JVM编程语言),float相关逻辑正常,但double、long类型变量执行时抛出VerifyError,已在ClassWriter实例化时启用COMPUTE_MAXS和COMPUTE_FRAMES参数。
编译的源代码
float f = 2f float f2 = new Float(2f) Float f3 = f2 println(f2) double d = 2d double d2 = new Double(2d) Double d3 = d2 println(d2)
注:println对应System.out.println
生成的字节码(javap输出)
Code: 0: ldc #14 // float 2.0f 2: fstore_1 3: new #16 // class java/lang/Float 6: dup 7: ldc #14 // float 2.0f 9: invokespecial #19 // Method java/lang/Float."<init>":(F)V 12: invokevirtual #23 // Method java/lang/Float.floatValue:()F 15: fstore_2 16: fload_2 17: invokestatic #27 // Method java/lang/Float.valueOf:(F)Ljava/lang/Float; 20: astore_3 21: getstatic #33 // Field java/lang/System.out:Ljava/io/PrintStream; 24: fload_2 25: invokevirtual #38 // Method java/io/PrintStream.println:(F)V 28: ldc2_w #39 // double 2.0d 31: dstore 4 33: new #42 // class java/lang/Double 36: dup 37: ldc2_w #39 // double 2.0d 40: invokespecial #45 // Method java/lang/Double."<init>":(D)V 43: invokevirtual #49 // Method java/lang/Double.doubleValue:()D 46: dstore 5 48: dload 5 50: invokestatic #52 // Method java/lang/Double.valueOf:(D)Ljava/lang/Double; 53: astore 6 55: getstatic #33 // Field java/lang/System.out:Ljava/io/PrintStream; 58: dload 5 60: invokevirtual #54 // Method java/io/PrintStream.println:(D)V 63: aconst_null 64: areturn
执行错误信息
Exception in thread "main" java.lang.VerifyError: Bad local variable type Exception Details: Location: Test.run()Ljava/lang/Object; @58: dload Reason: Type top (current frame, locals[5]) is not assignable to double Current Frame: bci: @58 flags: { } locals: { 'Test', float, float, 'java/lang/Float', top, top, 'java/lang/Double' } stack: { 'java/io/PrintStream' }
问题原因分析
- JVM局部变量表规则:double、long类型在局部变量表中会占用2个连续的槽位,执行
dstore n时,实际会将值存入索引n和n+1的槽位。 - 索引分配冲突:
- 字节码中
dstore 4将double d存入索引4、5的槽位; - 后续
dstore 5试图将double d2存入索引5、6的槽位,此时已占用d的第二个槽位; - 紧接着
astore 6将Double d3存入索引6的槽位,直接覆盖了d2需要的第二个槽位,导致d2的局部变量存储被破坏,索引5的槽位变为无效的top类型。
- 字节码中
- ASM参数局限性:
COMPUTE_MAXS和COMPUTE_FRAMES仅负责计算栈大小和栈帧信息,无法纠正局部变量索引分配的逻辑错误。
解决方法
- 修正局部变量索引分配逻辑:
- 对于引用类型、float、int等占用1个槽位的变量,分配索引后将下一个可用索引+1;
- 对于double、long类型变量,分配索引后将下一个可用索引+2,确保两个连续槽位不会被后续变量占用。
- 调整示例中的索引分配:
double d应存入索引4,下一个可用索引为6;double d2存入索引6,占用6、7槽位;Double d3存入索引8,避免覆盖d2的槽位。
内容的提问来源于stack exchange,提问作者Tambapps
相关产品推荐
相关产品推荐

