局部變量區(qū)
每個Java方法使用一個固定大小的局部變量集。它們按照與vars寄存器的字偏移量來尋址。局部變量都是32位的。長整數(shù)和雙精度浮點數(shù)占據(jù)了兩個局部變量的空間,卻按照個局部變量的索引來尋址。(例如,一個具有索引n的局部變量,如果是一個雙精度浮點數(shù),那么它實際占據(jù)了索引n和n+1所代表的存儲空間)虛擬機規(guī)范并不要求在局部變量中的64位的值是64位對齊的。虛擬機提供了把局部變量中的值裝載到操作數(shù)棧的指令,也提供了把操作數(shù)棧中的值寫入局部變量的指令。
運行環(huán)境區(qū)
在運行環(huán)境中包含的信息用于動態(tài)鏈接,正常的方法返回以及異常捕捉。
動態(tài)鏈接
運行環(huán)境包括對指向當前類和當前方法的解釋器符號表的指針,用于支持方法代碼的動態(tài)鏈接。方法的class文件代碼在引用要調用的方法和要訪問的變量時使用符號。動態(tài)鏈接把符號形式的方法調用翻譯成實際方法調用,裝載必要的類以解釋還沒有定義的符號,并把變量訪問翻譯成與這些變量運行時的存儲結構相應的偏移地址。動態(tài)鏈接方法和變量使得方法中使用的其它類的變化不會影響到本程序的代碼。
正常的方法返回
如果當前方法正常地結束了,在執(zhí)行了一條具有正確類型的返回指令時,調用的方法會得到一個返回值。執(zhí)行環(huán)境在正常返回的情況下用于恢復調用者的寄存器,并把調用者的程序計數(shù)器增加一個恰當?shù)臄?shù)值,以跳過已執(zhí)行過的方法調用指令,然后在調用者的執(zhí)行環(huán)境中繼續(xù)執(zhí)行下去。
操作數(shù)棧
機器指令只從操作數(shù)棧中取操作數(shù),對它們進行操作,并把結果返回到棧中。選擇棧結構的原因是:在只有少量寄存器或非通用寄存器的機器(如Intel486)上,也能夠地模擬虛擬機的行為。操作數(shù)棧是32位的。它用于給方法傳遞參數(shù),并從方法接收結果,也用于支持操作的參數(shù),并保存操作的結果。例如,iadd指令將兩個整數(shù)相加。相加的兩個整數(shù)應該是操作數(shù)棧頂?shù)膬蓚€字。這兩個字是由先前的指令壓進堆棧的。這兩個整數(shù)將從堆棧彈出、相加,并把結果壓回到操作數(shù)棧中。
每個原始數(shù)據(jù)類型都有專門的指令對它們進行必須的操作。每個操作數(shù)在棧中需要一個存儲位置,除了long和double型,它們需要兩個位置。操作數(shù)只能被適用于其類型的操作符所操作。例如,壓入兩個int類型的數(shù),如果把它們當作是一個long類型的數(shù)則是非法的。在Sun的虛擬機實現(xiàn)中,這個限制由字節(jié)碼驗證器強制實行。但是,有少數(shù)操作(操作符dupe和swap),用于對運行時數(shù)據(jù)區(qū)進行操作時是不考慮類型的。
本地方法棧,當一個線程調用本地方法時,它就不再受到虛擬機關于結構和限制方面的約束,它既可以訪問虛擬機的運行期數(shù)據(jù)區(qū),也可以使用本地處理器以及任何類型的棧。例如,本地棧是一個C語言的棧,那么當C程序調用C函數(shù)時,函數(shù)的參數(shù)以某種順序被壓入棧,結果則返回給調用函數(shù)。在實現(xiàn)Java虛擬機時,本地方法接口使用的是C語言的模型棧,那么它的本地方法棧的調度與使用則完全與C語言的棧相同。