深入理解 JVM(3)運行時數據區域

轉載請註明原創出處,謝謝!

HappyFeet的博客

Java 虛擬機在執行 Java 程序的過程中會把它所管理的內存劃分爲若干個不同的數據區域。這些區域都有各自的用途,以及創建和銷燬時間,有的區域隨着虛擬機進程的啓動而存在,有的區域則依賴用戶線程的啓動和結束而創建和銷燬。根據《Java 虛擬機規範(Java SE 7 版)》的規定,Java 虛擬機所管理的內存將會包括以下幾個運行數據區域:

運行時數據區域

理解 JVM 運行時數據區域有助於我們分析 OOM 異常。


1、程序計數器(PC)

程序計數器是一塊較小的內存空間,它可以看作是當前現成所執行的字節碼的行號指示器。線程私有,該內存區域是唯一一個在 Java 虛擬機規範中沒有規定任何 OutOfMemoryError 情況的區域。

2、Java 虛擬機棧

線程私有。虛擬機棧描述的是 Java 方法執行的內存模型:每個方法在執行的同時都會創建一個棧幀用於存儲局部變量表、操作數棧、動態鏈接、方法出口等信息。

如果線程請求的棧深度大於虛擬機所允許的深度,將拋出 StackOverflowError 異常;如果虛擬機棧可以動態擴展,如果擴展時無法申請到足夠的內存,就會拋出 OutOfMemoryError 異常。

3、本地方法棧

與虛擬機棧作用類似,區別在於虛擬機棧爲虛擬機執行 Java 方法服務,而本地方法棧則爲虛擬機使用到的 native 方法服務。

4、Java 堆

線程共享,是虛擬機所管理的內存中最大的一塊。該區域目的就是爲了存放對象實例;同時它也是垃圾收集器管理的主要區域。分爲新生代和老生代,分別採用不同的垃圾收集算法。可以通過 -Xmx-Xms 來指定堆的最大內存和最小內存。當堆中沒有內存完成實例分配,並且堆也無法擴展時,將會拋出 OutOfMemoryError 異常。

5、方法區

方法區和 Java 堆一樣,是各個線程共享的內存區域,它用於存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼等數據。

當方法區無法滿足內存分配需求時,將拋出 OutOfMemoryError 異常。

6、運行時常量池

運行時常量池是方法區的一部分。常量池存放的是編譯期生成的各種字面量和符號引用,在類加載完成後進入方法區的運行時常量池。

7、直接內存

直接內存不是虛擬機運行時數據區的一部分,也不是 Java 虛擬機規範中定義的內存區域。但是這部分內存也被頻繁地使用。

參考資料:

(1)《深入理解 Java 虛擬機》周志明 著.

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