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

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' }

问题原因分析

  1. JVM局部变量表规则:double、long类型在局部变量表中会占用2个连续的槽位,执行dstore n时,实际会将值存入索引n和n+1的槽位。
  2. 索引分配冲突:
    • 字节码中dstore 4将double d存入索引4、5的槽位;
    • 后续dstore 5试图将double d2存入索引5、6的槽位,此时已占用d的第二个槽位;
    • 紧接着astore 6将Double d3存入索引6的槽位,直接覆盖了d2需要的第二个槽位,导致d2的局部变量存储被破坏,索引5的槽位变为无效的top类型。
  3. ASM参数局限性:COMPUTE_MAXS和COMPUTE_FRAMES仅负责计算栈大小和栈帧信息,无法纠正局部变量索引分配的逻辑错误。

解决方法

  1. 修正局部变量索引分配逻辑:
    • 对于引用类型、float、int等占用1个槽位的变量,分配索引后将下一个可用索引+1;
    • 对于double、long类型变量,分配索引后将下一个可用索引+2,确保两个连续槽位不会被后续变量占用。
  2. 调整示例中的索引分配:
    • double d应存入索引4,下一个可用索引为6;
    • double d2存入索引6,占用6、7槽位;
    • Double d3存入索引8,避免覆盖d2的槽位。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 01:05:18