亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Java 字節碼中的 Stack=4。Java 編譯器如何計算 4 的值?

Java 字節碼中的 Stack=4。Java 編譯器如何計算 4 的值?

慕斯709654 2022-05-21 20:43:18
Java 代碼:public class SimpleRecursion {    public int factorial(int n) {        if (n == 0) {            return 1;        }        return n * factorial(n - 1);    }}為階乘方法提供以下字節碼(我執行 javap 來生成它):public int factorial(int); descriptor: (I)I flags: ACC_PUBLIC Code:     stack=4, locals=2, args_size=2     0: iload_1     1: ifne          6     4: iconst_1     5: ireturn     6: iload_1     7: aload_0     8: iload_1     9: iconst_1    10: isub    11: invokevirtual #2                  // Method factorial:(I)I    14: imul    15: ireturn     LineNumberTable:    line 4: 0    line 5: 4    line 7: 6     StackMapTable: number_of_entries = 1    frame_type = 6 /* same */我知道在上面塊的第五行中,stack=4 意味著堆棧最多可以有 4 個 objects。但是編譯器是如何計算的呢?
查看完整描述

1 回答

?
12345678_0001

TA貢獻1802條經驗 獲得超5個贊

由于棧的初始狀態,以及每條指令對它的影響是眾所周知的,你可以精確地預測,在任何時候,操作數棧上會出現什么樣的項:


[ ]            // initially empty

[ I ]          0: iload_1

[ ]            1: ifne          6

[ I ]          4: iconst_1

[ ]            5: ireturn

[ I ]          6: iload_1

[ I O ]        7: aload_0

[ I O I ]      8: iload_1

[ I O I I ]    9: iconst_1

[ I O I ]     10: isub

[ I I ]       11: invokevirtual #2   // Method factorial:(I)I

[ I ]         14: imul

[ ]           15: ireturn   

JVM 的驗證器會這樣做,在每條指令之后預測堆棧的內容,以檢查它是否適合作為后續指令的輸入。但它在這里有幫助,有一個聲明的最大大小,所以驗證器不需要維護一個動態增長的數據結構或為理論上可能的 64k 堆棧條目預分配內存。使用聲明的最大大小,它可以在遇到會推送更多的指令時停止,因此它永遠不需要比聲明更多的內存。


如您所見,聲明的最大堆棧大小恰好iconst_1在索引 9 處的指令之后達到一次。


然而,這并不意味著編譯器必須執行這樣的指令分析。編譯器具有從源代碼派生的代碼的更高級別模型,稱為抽象語法樹。


該結構將用于生成生成的字節碼,并且它還可能已經能夠預測該級別所需的堆棧大小。但是編譯器實際上是如何做到的,是依賴于實現的。


查看完整回答
反對 回復 2022-05-21
  • 1 回答
  • 0 關注
  • 173 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號