簡體   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

我正在嘗試使用 Java Asm 庫生成 Java 字節碼(我基本上是在嘗試創建另一種 JVM 編程語言)

這是我正在編譯的代碼

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)

如您所見,語法與 Java 非常相似println只是對System.out.println的調用。

當我使用我的編譯器時,它會生成以下代碼(使用 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

但是當我執行此代碼時,出現以下錯誤

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

我在實例化我的 ClassWriter 時使用了COMPUTE_MAXSCOMPUTE_FRAMES

我一直在看這個字節碼好幾次(甚至問過 ChatGPT 哈哈),但找不到問題所在。 據我所知,我在變量 5 中存儲了一個原始雙精度數,然后我想加載它以調用 println(double)。 我不明白為什么 Java 會告訴我這個錯誤。 它適用於第一部分使用 float,但不適用於雙打。 我對 long 類型有同樣的問題,但對 int 沒有

有人可以幫我找到我錯過的東西嗎?

您違反了 JVMS §2.6.1

2.6.1. 局部變量

每個幀(第 2.6 節)都包含一個稱為局部變量的變量數組。 幀的局部變量數組的長度在編譯時確定,並以 class 或接口的二進制表示以及與幀關聯的方法的代碼(§4.7.3)提供。

單個局部變量可以保存 boolean、byte、char、short、int、float、reference 或 returnAddress 類型的值。 一對局部變量可以保存 long 或 double 類型的值。

局部變量通過索引尋址。 第一個局部變量的索引為零。 integer 被認為是局部變量數組的索引,當且僅當 integer 介於零和比局部變量數組的大小小一之間時。

long 或 double 類型的值占用兩個連續的局部變量。 這樣的值只能使用較小的索引來尋址。 例如,在索引為 n 的局部變量數組中存儲的一個 double 類型的值實際上占用了索引為 n 和 n+1 的局部變量; 但是,無法從索引 n+1 處加載局部變量。 可以存入。 但是,這樣做會使局部變量 n 的內容無效。

Java虛擬機不要求n為偶數。 直觀地說,long 和 double 類型的值不需要在局部變量數組中進行 64 位對齊。 實現者可以自由決定使用為值保留的兩個局部變量來表示此類值的適當方式。

Java 虛擬機使用局部變量在方法調用時傳遞參數。 在 class 方法調用中,任何參數都從局部變量 0 開始傳入連續的局部變量。在實例方法調用中,局部變量 0 始終用於傳遞對調用實例方法的 object 的引用(這在 Java編程語言)。 從局部變量 1 開始,隨后將任何參數傳遞到連續的局部變量中。

(強調我的)

你在槽 5 中存儲一個雙精度數(它占用槽 5 和 6),然后你在槽 6 中存儲一些東西,從而使槽 5 中的變量無效。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM