Java虛擬機內存管理詳解

Java虛擬機在運行Java程序的過程會把它管理的內存劃分爲幾個不同的數據區域。每個區域有自己的用途,以及創建和銷燬的時間,有的區域伴隨着虛擬機的啓動而存在,有的區域則依賴用戶線程的啓動和結束而建立和銷燬。具體分爲以下幾部分內存管理區域:

程序計數器

程序計數器可以看做是當前線程所執行的字節碼的行號器。字節碼解釋器工作是就是通過這個程序計數器的值來選取下一條需要執行的字節碼指令,分支、循環、跳轉、異常處理、線程恢復等基礎功能都需要依賴程序計數器來完成。由於Java虛擬機的多線程是通過線程輪流切換並分配處理器執行時間的方式來實現的,一個處理器只會執行一條線程指令。因此,爲了保證線程切換後能夠恢復到正確的位置,每條線程都對應一個程序計數器,各個線程之間互相不受影響。

虛擬機棧

虛擬機棧描述的是Java方法執行的內存模型:每個方法在執行的時候都會創建一個棧幀用於存儲局部變量表、操作數棧、動態鏈接、方法出口等信息。每一個方法從調用至執行完成的過成,就是對應着一個棧幀在虛擬機中從入棧到出棧的過程。

局部變量表中存放的是編譯期可知的基本數據類型、對象引用(reference類型,它不等於對象本身,可能是一個指向對象起始地址的引用指針,也可能是指向一個代表對象的句柄或者是其他與此對象相關的位置)和returnAddress類型(指向了一條字節碼指令的地址)。其中64位長度的double和long類型的數據會佔用2個局部變量空間,其餘的類型只佔用1個。局部變量所需要的內存空間在編譯期間完成分配,當進入一個方法是,這個方法所需要在幀中分配多大的局部變量空間是完全確定的,在方法運行期間不會改變局部表裏表的大小。

在該區域會出現兩種異常狀況:如果線程請求的深度大於虛擬機所允許的深度,將拋出StackOverflowError異常;如果虛擬機動態擴展是無法申請到足夠的內存,就會拋出OutOfMemoryError異常。

本地方法棧

本地方法棧和虛擬機棧所發揮的作用是非常相似的,不同之處在於虛擬機棧爲虛擬機執行Java方法服務,而本地方法棧則爲虛擬機使用到的Native方法服務。與虛擬機棧一樣,本地方法棧區域也會拋出StackOverflowError和OutOfMemoryError異常。

Java堆

Java堆是虛擬機所管理內存中最大的一塊,Java堆是被所有線程共享的一塊內存區域,在虛擬機啓動是創建。此區域的唯一目的就是存放對象實例,幾乎所有的對象實例都在這裏分配。Java堆是垃圾收集器管理的主要區域,從內存回收的角度來看,由於收集器都是採用分代收集算法,所以Java堆可以細分爲:新生代和老年代;再細緻一點的有Eden空間、From Survivor空間、To Surivivor空間。

Java堆可以處理物理上不連續的內存空間中,只要邏輯上連續的即可,就像我們的磁盤空間一樣。如果在堆中沒有內存完成實例分配,並且堆無法再擴展是,將會拋出OutOfMemoryError異常。

方法區

方法區與Java堆一樣,是各個線程共享的內存區域,它用於存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼等數據。當方法區無法滿足內存分配需求時,將拋出OutOfMemoryError異常。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章