總是記不住這幾個運行時數據區,還是再捋一遍吧。
常見分類,一共5個區域,分爲2種類型:
- 線程共享
- 方法區 Method Area
- 堆內存 Heap
- 線程獨享
- 虛擬機棧 VM Stack
- 本地方法棧 Native Method Stack
- 程序計數器 Program Counter Register
1.方法區
存儲已被虛擬機加載的類型信息、常量、靜態變量、即時編譯後的代碼緩存等數據。
JDK6時,計劃放棄永久代,逐步改爲本地內存來實現方法區的計劃;
JDK7,把原本放在永久代的字符串常量池、靜態變量等移出;
JDK8,完全廢棄永久代的概念,改用在本地內存中實現的元空間Meta-space來代替,把JDK7遺留的(主要是類型信息)全部移到元空間中。
2.堆內存
G1收集器出現爲分界,之前,業界絕對主流的Hotspot虛擬機,內部垃圾收集器全部都基於“經典分代”來設計,需要新生代、老年代收集器搭配才能工作;之後,Hotspot虛擬機裏也出現了不採用分代設計的新垃圾收集器。
所有線程共享的Java堆中,可以劃分出多個線程私有的分配緩衝區(Thread Local Allocation Buffer, TLAB),以提升對象分配時的效率。
3.虛擬機棧 Java Virtual Machine Stack
爲虛擬機執行Java方法(字節碼)服務。
線程私有,生命週期與線程相同。
線程棧由多個棧幀(Stack Frame)組成。
棧幀用於存儲局部變量表、操作數棧、動態連接、方法出口、附加信息等。
兩類異常:
- 線程請求的棧深度大於虛擬機所允許的深度,將拋出StackOverflowError異常;
- Java虛擬機棧容量可以動態擴展,當棧擴展時無法申請到足夠的內存會拋出OutOfMemoryError異常。
4.本地方法棧 Native Method Stacks
爲虛擬機使用到的本地(Native)方法服務。
線程私有,生命週期與線程相同。
Hotspot虛擬機直接把本地方法棧和虛擬機棧合二爲一。
StackOverflowError異常和OutOfMemoryError異常。
5.程序計數器 Program Counter Register
程序控制流的指示器,分支、循環、跳轉、異常處理、線程恢復等基礎功能都需要依賴程序計數器來完成。
Java虛擬機多線程實現方式:通過線程輪流切換、分配處理器執行時間。
線程執行的Java方法,計數器記錄的是正在執行的虛擬機字節碼指令的地址。
線程執行的本地方法,計數器值爲空(Undefined)。
此內存區域是唯一一個在規範中沒有規定任何OutOfMemoryError情況的區域。