1. 程式人生 > >JVM之執行時資料區域詳解

JVM之執行時資料區域詳解

1、程式計數器        

        程式計數器是一塊較小的記憶體空間,它可以看作是當前執行緒所執行的位元組碼的行號指示器虛擬機器工作時就是通過改變改變計數器的值來選取下一條需要執行的位元組碼指令,分支、迴圈、跳轉、異常處理、執行緒恢復等基礎功能都需要依賴這個計數器來完成。

        Java虛擬機器多執行緒使通過輪流切換並分配處理器執行時間的方式實現,一個處理器(對於多核處理器來說就是一個核心)在同一時間只會處理一條指令,因此為了執行緒執行完畢後能恢復到正常狀態,每個執行緒都需要有一個獨立的程式計數器,我們稱這塊記憶體為 “執行緒私有” 的記憶體。

        特別注意,如果當前執行緒正在執行的是java方法,這個計數器就會記錄正在執行的位元組碼指令的地址了;如果執行的是native方法,那麼這個計數器為空。此記憶體域是jvm中唯一一個沒被規定OutOfMemoryError的區域

2、JAVA虛擬機器棧

        java虛擬機器棧(以下簡稱java棧)也是執行緒私有的,他的生命週期與執行緒相同。每個方法執行時都會建立一個棧幀,用來儲存區域性變量表、運算元棧、動態連結、方法出口等資訊,每一個方法從呼叫到執行完成的過程,就對應著一個棧幀從虛擬機器棧中執行入棧到出棧的過程。

        區域性變量表存放了編譯器可知的各種資料型別,其中64位長度的long和double佔兩個基本資料型別。

        在JVM規範中,對這個區域規定了兩種異常情況:1、如果執行緒請求的棧深度大於虛擬機器所允許的深度,將會丟擲StackOverflow異常;2、如果虛擬機器棧是可以動態擴充套件的,如果擴充套件時無法申請到足夠的記憶體,就會丟擲OutOfMemoryError異常。

3、本地方法棧

         本地虛擬棧與虛擬機器棧非常相似,只不過虛擬機器棧執行的時java方法(位元組碼)服務,而本地方法棧則為支援虛擬機器能使用native方法服務

4、Java堆

        Java堆時Java虛擬機器所管理的一塊最大的記憶體。Java堆是被所有執行緒共享的一塊記憶體區域,虛擬機器啟動時建立。此記憶體區域唯一的目的就是存放物件的例項,幾乎所有的物件的例項化都分配在這塊記憶體中

        Java堆是垃圾收集器管理的主要區域,因此很多時候也被稱為 “GC堆” 。

        Java堆可以處於物理上不連續的記憶體空間中,只要邏輯上連續即可。在實現是既可以固定大小,也可以是可擴充套件的,不過現在主流的虛擬機器都是按照可擴充套件來實現的,如果沒有足夠的記憶體分配給例項,並且堆也無法擴充套件時,就會爆出OutMemoryerror異常。

5、方法區

        方法區也是各個執行緒共享的一塊記憶體區域,它用於儲存已經被虛擬機器載入的類資訊、常量、靜態變數、即時編譯器編譯後的程式碼等資料。特別注意:雖然JVM規範將方法去描述為堆的一個邏輯部分,但他應該跟Java堆區分開來。

        Java虛擬機器規範堆方法去的限制非常寬鬆,除了和Java堆一樣不需要連續的實體地址空間和可以選擇固定大小或可拓展,它還可以選擇不實現垃圾回收。

6、執行時常量池

         執行時常量池是方法去的一部分。Class檔案中除了有類的版本、欄位、方法、介面等資訊外,還有一項資訊是常量池,用於存放編譯器生成的各種字面量和符號引用,這部分內容將在類載入後進入方法區的執行時常量池中存放

        執行時常量池相對於Class檔案常量池的另外一個重要特徵是具備動態性,即常量不一定只會在編譯時才產生,也就是說可以在類沒有載入時,常量池就可以有內容,這種特性被開發人員利用的比較多的便是String類的intern()方法。

7、直接記憶體

        之際記憶體並不是JVM執行時資料區的一部分,但是這部分記憶體在JVM執行時也被大量使用。