java returnaddress_Java虚拟机规范】Java SE 7虚拟机结构
引言
Java虛擬機可以看做是一臺抽象的計算機,如同真實的計算機那樣,有自己的指令集以及各種運行時內存區域。Java虛擬機與Java語言沒有必然聯系,它只與特定的二進制文件即Class文件關聯,Class文件包含了Java虛擬機指令(字節碼),符號表以及一些需要的輔助信息。任何一種語言只要可以被編譯成有效的Class文件,都可以在Java虛擬機上面運行。
1.數據類型
Java虛擬機可以操作的數據類型分為兩類,原始類型(Primitive Types)與引用類型(Reference Types)。原始類型不需要額外的手段來確定運行期他們實際的數據類型,指令本身就可以確定;引用類型編譯器應當在編譯期間盡最大努力完成類型檢查。
2.原始類型與值
原始類型包括數值類型(Numberic Types)、布爾類型(Boolean Type)和returnAddress類型。
數值類型:整數類型byte short int long char,浮點類型float double,與IEEE 754格式取值和操作一致。
布爾類型:Java虛擬機定義了boolean這種數據類型,但是沒有指令支持,涉及到boolean值類型的運算,都會被編譯成int類型來代替。
returnAddress類型:被指令jsr,jsr_w,ret使用,從JDK7開始虛擬機不允許出現這幾條指令,所以不用過于關注。returnAddress類型的值指向一條虛擬機指令的操作碼,初衷是用來實現Java語言中的finally語句塊。jsr與ret是一起使用的,jsr跳轉到指定的offet位置,并將jsr下一條指令壓入棧頂,就是retureAddress類型了,使用ret返回到指定的指令位置。參考:)
3.引用類型與值
類類型(Class Types) 數組類型(Array Types) 接口類型(Interface Types),分別對應類實例,數組實例,實現某個接口的實例。
引用類型值有一個特殊的值null,當一個引用不指向任何對象時,它的值用null表示,可以轉換為任意類型,Java虛擬機沒有規定null的實現應用用怎樣的編碼。
4.運行時數據區
運行時數據區
PC(Program Counter)寄存器:Java虛擬機中每一條線程都有自己的PC寄存器,用來保存當前方法的指令地址(也就是returenAddress類型的值),如果方法是native的,則保存本地指針的值。
Java虛擬機棧(Java Virtual Machine Stack):Java虛擬機每一條線程都有私有的棧,用來存儲局部變量與一些過程結果的地方,由棧幀(Frames)組成。Java虛擬機棧能夠被實現成固定大小或者動態擴展模型。異常情形:(1)如果線程請求分配的棧容量超過Java虛擬機棧允許的最大容量,則拋出StackOverflowError異常 (2)如果Java虛擬機棧能夠動態擴展,申請不到內存去創建新的棧,則拋出OutofMemoryError異常。
Java堆(Heap) :堆區是線程共享的區域,用分配類實例,數組對象的內存區域。Java虛擬機啟動的時候就會被創建,并且分配的內存由GC(Garbage Collector)管理,這些對象無需也無法顯示地被銷毀。當創建的堆超過了GC能夠提供的容量,則會拋OutofMemoryError異常。
方法區(Method Aera):Java虛擬機啟動時創建,線程共享的內存區域,編譯代碼(類信息,類方法,成員變量,運行時常量等信息)的存儲區域。雖然方法區是堆區的邏輯組成部分,虛擬機實現可以選擇是否回收該區域垃圾。方法區內存空間不滿足內存分配要求,同樣拋出OutOfMemoryError。
運行時常量池(Rumtime Constant Pool): 類似符號表,從編譯時可以知道的字面量到必須運行是解析后才能知道的方法或者字段引用,位于方法區中,在類和接口被創建,對應的運行時常量池就被創建。
本地方法棧(Native Method Stack): 用來支持native方法的執行,在線程創建時分配。和虛擬機棧類似,能夠動態擴展,棧容量超過本地方法棧允許最大容量拋StackOverflowError,無法申請到足夠的內存去擴展拋OutOfMemoryError。
4.棧幀(Frame)
用來存儲數據或部分過程結果的數據結構,處理動態鏈接(Dynamic Linking)、方法返回值、異常分派(Dispatch Exception)。隨著方法調用創建,方法結束銷毀。每一個棧幀都有自己的局部變量表(Local Variables),操作數棧(Operand Stack)和指向當前方法所屬的類的運行時常量池的引用,并且容量是在編譯期確定的。
棧幀是線程本地私有數據,不可能在一個棧幀之中訪問另一條線程的棧幀。
局部變量表:局部變量表可以保存前面所述的虛擬機的數據類型,其中兩個局部變量保存一個類型為long或double的數據。局部變量表使用索引來訪問,可以想象為一個數組的模型,當方法調用時,它的參數從零開始連續的存放在局部變量表示,如果是實例方法,則第0個局部變量一定是調用方法對象的引用(即Java里的this)。
操作數棧:后進先出(Last-In-First-Out,LIFO)棧,用來存放Java虛擬的指令執行時操作數以及執行后的結果,操作數棧與局部變量表可以相互轉移。在方法調用的時候,操作數棧用來準備調用方法的參數以及接收方法返回結果。
每一個棧幀內部都包含一個指向運行時常量池的引用來支持當前方法的代碼實現動態鏈接,方法調用或者訪問成員變量時是通過符號引用表示,動態鏈接的作用就是將符號引用轉化為實際的方法引用。
5.浮點算法
Java虛擬機中浮點操作在遇到非法操作(如被零整除,上限溢出等)不會拋exception。
6.初始化方法
Java虛擬機層面上類實例的構造方法名為,在實例的初始化通過invokespecial指令調用。類和接口的初始化通過,在類加載時由Java虛擬機自身隱式調用,沒有任何指令可以調用這個方法。
7.異常
異常的本質是程序控制權的一種及時、非局部的轉換(從異常拋出的地方轉至處理異常的地方)。當前前程拋出的異常稱為同步異常,非當前線程拋出的異常為異步異常。虛擬機異常的情形有:
指令非正常執行,如數組越界,棧溢出等
athrow指令被執行
虛擬機內部錯誤或者Thread/ThreadGroup的stop方法被執行(異步異常)
Java虛擬機執行每一個方法都會配有零至多個異常處理器(Exception Handlers),每個方法的異常處理器都存儲在一個表中,在運行時出現異常后,會按照異常處理器的描述執行。
8.字節碼指令集簡介
Java虛擬機的指令有一個字節長度的操作碼(Opcode)和操作數(Operands)組成,由于操作碼為一個字節,所以虛擬機的字節碼指令最后有256條。
Java虛擬機解釋器偽代碼:
do {
自動計算PC寄存器以及從PC寄存器的位置取出操作碼
if(存在操作數)取出操作數
執行操作碼所定義的操作
}while(處理下一次循環);
由于Java虛擬機字節碼數量限制,對于特定類型操作只提供了有限的類型相關指令去操作它。多數對于boolean byte short char類的數據操作,實際上都是使用相應對int類型作為運算類型。
加載存儲指令:用于局部變量表與操作數棧之間來回傳輸,例如:
istore_1 指令作用是從操作數棧中彈出一個int型的值,并保存在第一個局部變量中
iload_1 指令作用是將第一個局部變量的值壓入操作數棧
運算指令:用于兩個操作數棧上的值進行運算,并把結果重新存入操作數棧棧頂。例如iadd isub,Java虛擬機沒有明確規定整型數據溢出情況,但規定除法指令(idiv/ldiv),求余指令(irem和lrem)的除數為零時拋ArithmeitcException異常。
類型轉換指令:Java虛擬機直接支持寬化類型轉換(Widening Numberic Conversions),如int類型到long float double類型,long 到float double類型。 窄化類型轉換(Narrowing Numberic Conversions)會導致符號位丟失,精度丟失,指令有i2b i2c f2i f2l等等。
對象創建與操作:類實例與數組都是對象,使用不同的指令操作。
創建對象new,創建數組newarray anewarray multinewarray。
訪問字段getfield putfield getstatic putstatic
加載數組元素到操作數棧:iaload aaload等
將操作數棧的值存儲到數組元素:iastore aastore等
取數組長度的指令arraylength
檢查類實例類型的指令instanceof checkcast
操作數棧管理:pop pop2 dup dup2 swap等
控制轉移指令:
條件分支:ifeq iflt...
復合條件分支:tableswitch lookupswitch
無條件:goto goto_w jsr ret..
方法調用和返回指令:四條指令用于方法調用,
invokevirtial 調用實例方法
invokeinterface 調用接口方法
invokespecial 調用特殊的實例方法,例如實例初始化方法,私有方法以及父類方法
invodestatic 調用靜態方法
方法返回指令 ireturn(同樣,boolean byte char short int類型時時候) areturn return(返回類型類void)
拋出異常:顯式拋出的指令athrow,Java虛擬機檢測到指令執行異常由Java虛擬機自動拋出。
同步:方法級同步時隱式的,常量池的方法列表里面指令。指令序列同步的關鍵字 monitorennter monitorexit,對應Java中sychronized的代碼塊。
8.類庫
Java虛擬機必須對不同平臺下的Java類庫提供充分的實現,某些與操作系統密切相關的類庫需要Java虛擬機的本地方法來實現:
反射 java.lang.relect包與java.lang.Class類
類和接口的加載與創建 java.lang.ClassLoader類
安全相關 java.lang.SecurityManager
多線程
弱引用
9.公有設計,私有實現
虛擬機實現必須能夠讀取Class文件,并且精確實現虛擬機代碼的含義,怎么實現是實現者自己的事情,只要外部接口看起來與規范描述的一樣。目前虛擬機實現方式主要有兩種:
將輸入的Java虛擬代碼在加載的時或執行時翻譯成另外一種虛擬機指令集。(如Davilk)
將輸入的Java虛擬機代碼在加載時或執行時翻譯成宿主機CPU的本地指令集(如ART)
總結
以上是生活随笔為你收集整理的java returnaddress_Java虚拟机规范】Java SE 7虚拟机结构的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java中接口什么时候用_我什么时候应该
- 下一篇: java转换音频采样率_转换音频采样率