简体   繁体   English

Java ASM:错误的局部变量类型 (dload) 类型 top(当前帧,locals[5])不可分配给 double

[英]Java ASM: Bad local variable type (dload) Type top (current frame, locals[5]) is not assignable to double

I am trying to generate Java bytecode using the Java Asm library (I am basically trying to create yet another JVM programming language)我正在尝试使用 Java Asm 库生成 Java 字节码(我基本上是在尝试创建另一种 JVM 编程语言)

Here is the code I am compiling这是我正在编译的代码

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)

As you can see the syntax is very similar to Java. println is just a call to System.out.println .如您所见,语法与 Java 非常相似println只是对System.out.println的调用。

When I use my compiler, it generates the following code (got this output using javap)当我使用我的编译器时,它会生成以下代码(使用 javap 得到这个 output)

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

But when I execute this code I get the following error但是当我执行此代码时,出现以下错误

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

I've used the COMPUTE_MAXS and COMPUTE_FRAMES when instantiating my ClassWriter我在实例化我的 ClassWriter 时使用了COMPUTE_MAXSCOMPUTE_FRAMES

I've been looking at this bytecode several times (and even asked ChatGPT lol) but couldn't find what is wrong.我一直在看这个字节码好几次(甚至问过 ChatGPT 哈哈),但找不到问题所在。 From what I see, I've stored a primitive double in variable 5, and then I want to load it to invoke println(double).据我所知,我在变量 5 中存储了一个原始双精度数,然后我想加载它以调用 println(double)。 I don't understand why Java is telling me this error.我不明白为什么 Java 会告诉我这个错误。 It worked for the first part using float, but doesn't with doubles.它适用于第一部分使用 float,但不适用于双打。 I've got the same problem with long type, but not with int我对 long 类型有同样的问题,但对 int 没有

Can someone help me find what I missed?有人可以帮我找到我错过的东西吗?

You violate JVMS §2.6.1 :您违反了 JVMS §2.6.1

2.6.1. 2.6.1. Local Variables局部变量

Each frame (§2.6) contains an array of variables known as its local variables.每个帧(第 2.6 节)都包含一个称为局部变量的变量数组。 The length of the local variable array of a frame is determined at compile-time and supplied in the binary representation of a class or interface along with the code for the method associated with the frame (§4.7.3).帧的局部变量数组的长度在编译时确定,并以 class 或接口的二进制表示以及与帧关联的方法的代码(§4.7.3)提供。

A single local variable can hold a value of type boolean, byte, char, short, int, float, reference, or returnAddress.单个局部变量可以保存 boolean、byte、char、short、int、float、reference 或 returnAddress 类型的值。 A pair of local variables can hold a value of type long or double.一对局部变量可以保存 long 或 double 类型的值。

Local variables are addressed by indexing.局部变量通过索引寻址。 The index of the first local variable is zero.第一个局部变量的索引为零。 An integer is considered to be an index into the local variable array if and only if that integer is between zero and one less than the size of the local variable array. integer 被认为是局部变量数组的索引,当且仅当 integer 介于零和比局部变量数组的大小小一之间时。

A value of type long or type double occupies two consecutive local variables. long 或 double 类型的值占用两个连续的局部变量。 Such a value may only be addressed using the lesser index.这样的值只能使用较小的索引来寻址。 For example, a value of type double stored in the local variable array at index n actually occupies the local variables with indices n and n+1;例如,在索引为 n 的局部变量数组中存储的一个 double 类型的值实际上占用了索引为 n 和 n+1 的局部变量; however, the local variable at index n+1 cannot be loaded from.但是,无法从索引 n+1 处加载局部变量。 It can be stored into.可以存入。 However, doing so invalidates the contents of local variable n.但是,这样做会使局部变量 n 的内容无效。

The Java Virtual Machine does not require n to be even. Java虚拟机不要求n为偶数。 In intuitive terms, values of types long and double need not be 64-bit aligned in the local variables array.直观地说,long 和 double 类型的值不需要在局部变量数组中进行 64 位对齐。 Implementors are free to decide the appropriate way to represent such values using the two local variables reserved for the value.实现者可以自由决定使用为值保留的两个局部变量来表示此类值的适当方式。

The Java Virtual Machine uses local variables to pass parameters on method invocation. Java 虚拟机使用局部变量在方法调用时传递参数。 On class method invocation, any parameters are passed in consecutive local variables starting from local variable 0. On instance method invocation, local variable 0 is always used to pass a reference to the object on which the instance method is being invoked (this in the Java programming language).在 class 方法调用中,任何参数都从局部变量 0 开始传入连续的局部变量。在实例方法调用中,局部变量 0 始终用于传递对调用实例方法的 object 的引用(这在 Java编程语言)。 Any parameters are subsequently passed in consecutive local variables starting from local variable 1.从局部变量 1 开始,随后将任何参数传递到连续的局部变量中。

(Emphasis mine) (强调我的)

You store a double in slot 5 (which occupies the slots 5 and 6), then you store something in slot 6, thereby invalidating the variable in slot 5.你在槽 5 中存储一个双精度数(它占用槽 5 和 6),然后你在槽 6 中存储一些东西,从而使槽 5 中的变量无效。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用 ASM 和 Javaagent 插入堆栈图帧时“类型不可分配给 uninitializedThis” - "Type is not assignable to uninitializedThis" when inserting stackmap frame using ASM and Javaagent 方法中的局部变量类型错误 - Bad local variable type in method java.lang.VerifyError:通过部署war文件错误的局部变量类型 - java.lang.VerifyError: Bad local variable type by deploying war file java.lang.VerifyError 的 JUnit 错误:Jenkins 上的局部变量类型错误 - JUnit error of java.lang.VerifyError: Bad local variable type on Jenkins 无法将类型“ org / springframework / http / MediaType”(当前框架,堆栈[1])分配给“ org / springframework / util / MimeType” - Type 'org/springframework/http/MediaType' (current frame, stack[1]) is not assignable to 'org/springframework/util/MimeType' 类型“org/eclipse/equinox/http/servlet/HttpServiceServlet”(当前帧,堆栈 [0])不可分配给“javax/servlet/http/HttpServlet” - Type 'org/eclipse/equinox/http/servlet/HttpServiceServlet' (current frame, stack[0]) is not assignable to 'javax/servlet/http/HttpServlet' 为什么我的Subflow抛出错误? (Java.lang.VerifyError:错误的局部变量类型) - Why is my Subflow throwing an error? (Java.lang.VerifyError: Bad local variable type) java.lang.VerifyError:字节码检测后局部变量类型错误 - java.lang.VerifyError: Bad local variable type after bytecode instrumentation Java中如何使用通配符作为局部变量的类型? - How to use wildcard as the type of local variable in Java? FTP Java程序中的运行时错误:类型top不可分配给“ java / net / socket” - Runtime error in FTP java program: Type top is not assignable to 'java/net/socket'
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM