Java運行時數據區

Java虛擬機定義了一些程序運行期間會使用到的數據區域,其中一些會隨着JVM的啓動而建立,隨着JVM的退出而銷燬;另一些則與線程的運行一一對立的,這些數據區域會隨着線程的開始而建立,隨着線程的結束而銷燬。下面是一張Java運行時的數據區模型圖:java

總的來講,Java運行時數據區域能夠分爲兩個部分:線程共享的區域和線程獨享的區域。下面一一對之進行總結。數組

1、線程共享區域:線程共享區域是指各個線程都會使用到的一塊空間區域,它們會在這裏申請空間、使用空間。根據具體提供功能不一樣,能夠劃分爲兩個部分,分別是Java堆、方法區。下面分別總結。數據結構

一、Java堆:Java堆是在虛擬機啓動的時候就被建立,它存儲了被自動內存管理系統(也即常說的垃圾收集器)所管理的各類對象,這些對象無需也沒法被顯示地銷燬。咱們建立的類的實例以及數組對象就存放在這個區域。Java堆所使用的內存不須要保證是連續的。Java堆可能出現的異常有:若是所需的堆超過了自動內存管理系統能提供的最大容量,則Java虛擬機會拋出一個OutOfMemoryError異常。函數

二、方法區:方法區也是供各個線程共享的運行時存儲區,它存儲了每個類的結構下信息,例如運行時常量池、字段和方法數據、構造函數和普通方法的字節碼內容等。方法區也是隨着虛擬機的啓動而被建立,它是Java堆的邏輯組成部分,可是JVM能夠選擇在這個區域不實行垃圾蒐集和壓縮。一樣,若是方法區的內存不能知足內存分配需求,則JVM將會拋出OutOfMemoryError異常。spa

三、運行時常量池:它是Class文件中每個類或接口的常量池表的運行時的表示形式。它包涵了若干不一樣的常量,從編譯期可知的數值字面量到必須在運行期解析後才能得到的方法或字段引用。每一個運行時常量池都在Java虛擬機的方法區分配,在類和接口加載到虛擬機後,就會建立對應的運行時常量池。當建立類和接口時,若是構造運行時常量池所需的內存空間超過了方法區所提供的最大值,JVM將會拋出OutOfMemoryError異常。線程

2、線程獨享區域:線程獨享區域是每一個線程都會單獨擁有的一塊區域,這塊區域是屬於線程內部的,它是用於存儲描述自身內部信息的區域。一樣,根據其提供 主要功能不一樣,一個線程內部具備的不一樣數據存儲區域能夠分爲如下幾個部分:對象

一、PC寄存器:PC(program counter)寄存器是用於記錄正在執行線程的內存地址的,由於一個線程不可能一直獨享CPU,當線程進行CPU切換時,必需要記錄下來當前線程的內存地址,以便在從新啓動線程時恢復之前的內存地址,在任意時刻,一條線程只會執行一個方法的代碼,這個正在被執行的方法被成爲該線程的當前方法(current method)。若是這個方法不是native的,那麼PC寄存器會保存JVM正在執行的字節碼指令的地址;若是該方法是native的,那麼PC寄存器的值是undefined。blog

二、本地方法戰:JVM可能會使用傳統的棧(一般稱爲 C stack)來支持native方法(指使用Java之外的其餘語言編寫的方法)的執行,這個棧就是本地方法棧(native method stack)。JVM規範容許本地方法棧實現成爲固定大小或者根據計算來動態擴展和收縮。若採用固定大小的本地方法棧,則每個線程的本地方法容量能夠在建立棧的時候獨立選定。接口

三、Java虛擬機棧:也就是常說的「Java棧」,每個JVM線程都有本身私有的Java虛擬機棧,該棧是與線程同時建立,用於存儲棧幀。它的做用是用於存儲一些還沒有計算好的結果,此外,它在方法的調用和返回中也具備重要的做用。JVM規範既容許java虛擬機棧被是現成固定大小,也容許根據計算來擴展和收縮。若採用固定大小的Java虛擬機棧,則每個線程的Java虛擬機棧容量能夠在線程建立的時候獨立選定。Java虛擬機棧可能發生的異常有:若是線程請求的棧容量超過java虛擬機棧所容許的最大容量,則java虛擬機會拋出StackOverflowError異常;若是java虛擬機棧能夠動態擴展,而且在嘗試擴展的時候沒法申請到足夠的內存或則建立新的線程時沒有足夠的內存去建立對應的虛擬機棧,則java虛擬機會拋出OutOfMemoryError異常。內存

四、棧幀:棧幀(frame)是用來存儲數據和部分過程結果的數據結構。同時也是用來處理動態連接(dynamic linking)、方法返回值和異常分派。棧幀隨着方法的調用而被建立,隨着方法的結束而被銷燬(不管是方法正常完成仍是異常完成)。棧幀的存儲空間是由建立它的線程分配在java虛擬機棧中的。每個棧幀都有本身的本地變量表(local variable)、操做數棧(operand stack)、指向當前方法所屬的類的運行時常量池的引用。在某個線程執行過程當中的某個時間點上,只有目前正在執行的那個方法的棧幀是活動的,這個棧幀被成爲當前棧幀(current frame),這個棧幀對應的方法稱爲當前方法(current method)、定義這個方法的類稱爲當前類(current class)。注意:棧幀是線程本地私有的數據,不能在一個棧幀之中引用另一個線程的棧幀

五、局部變量表:也叫本地變量表,它是用於存儲局部變量的列表。棧幀中的局部變量表的長度是由編譯期決定,並存儲與類或接口的二進制表示中。一個局部變量能夠保存一個類型爲boolean、byte、char、short、int、float的數據類型。兩個局部變量能夠保存一個類型爲long或double的數據。JVM使用局部變量表來完成方法調用時的參數傳遞

六、操做數棧:每一個棧幀內部均包含一個操做數棧,棧幀在剛被建立的時候,操做數棧是空的。JVM提供一些字節碼指令來從局部變量表或者對象的實例中複製常量或變量到操做數棧中,也提供了相關指令從操做數棧中取走數據、操做數據以及把操做結果從新入棧。任意時刻,操做數棧都會有一個肯定的棧深度,一個long、double類型的數據會佔用兩個深度的棧深度,其餘數據則會佔用一個棧深度。

六、動態連接:每一個棧幀都包含這樣一個引用,該引用是指向當前方法所在類型的運行時常量池,其做用是對當前代碼實現動態連接。一個方法要調用其餘方法,或則訪問成員變量,須要經過符號引用(symbolic reference)來表示,動態連接的做用就是將這些以符號引用所表示的方法轉換爲對實際方法的直接引用。因爲對其餘類中的方法和變量進行了晚期綁定(late binding),因此即使那些類發生變化,也不會影響調用它們的方法。

以上總結自《Java虛擬機規範》,感受內容仍是挺多的,加油!

相關文章
相關標籤/搜索