1 回答

TA貢獻(xiàn)1802條經(jīng)驗 獲得超5個贊
由于棧的初始狀態(tài),以及每條指令對它的影響是眾所周知的,你可以精確地預(yù)測,在任何時候,操作數(shù)棧上會出現(xiàn)什么樣的項:
[ ] // 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 的驗證器會這樣做,在每條指令之后預(yù)測堆棧的內(nèi)容,以檢查它是否適合作為后續(xù)指令的輸入。但它在這里有幫助,有一個聲明的最大大小,所以驗證器不需要維護(hù)一個動態(tài)增長的數(shù)據(jù)結(jié)構(gòu)或為理論上可能的 64k 堆棧條目預(yù)分配內(nèi)存。使用聲明的最大大小,它可以在遇到會推送更多的指令時停止,因此它永遠(yuǎn)不需要比聲明更多的內(nèi)存。
如您所見,聲明的最大堆棧大小恰好iconst_1在索引 9 處的指令之后達(dá)到一次。
然而,這并不意味著編譯器必須執(zhí)行這樣的指令分析。編譯器具有從源代碼派生的代碼的更高級別模型,稱為抽象語法樹。
該結(jié)構(gòu)將用于生成生成的字節(jié)碼,并且它還可能已經(jīng)能夠預(yù)測該級別所需的堆棧大小。但是編譯器實際上是如何做到的,是依賴于實現(xiàn)的。
添加回答
舉報