JVM的內存佈局

在這裏插入圖片描述

總體劃分

Java種由JVM來管理內存的分配和回收,JVM將內存區域總體可以分爲堆區和非堆區,非堆區又分爲JVM棧,方法區,本地方法棧,程序計數器等。其中堆區和方法區爲所有線程共享的數據區,其他爲各個線程私有的數據區。

Java堆

Java堆是JVM所管理的最大的一塊區域了,也是我們最關心的。幾乎所有的對象實例都在這裏分配。(JIT與逃逸分析技術使得對象也可以在棧上分配)

Java堆是垃圾收集器管理的主要區域,所以也被稱爲GC堆。從內存回收的角度看(分代收集算法),Java堆可以細分爲:新生代和老年代,更細一點有:Eden空間、From Survivor空間、To Survivor空間等。從內存分配的角度看,Java堆可劃分出多個線程私有的分配緩衝區(TLAB),主要用於小對象的分配。Java堆在物理空間可以不連續,只要邏輯上是連續的就可以。

關於TLAB
由於對象一般會分配在堆上,而堆是全局共享的。因此在同一時間,可能會有多個線程在堆上申請空間。因此,每次對象分配都必須要進行同步,而在競爭激烈的場合分配的效率又會進一步下降。JVM使用TLAB來避免多線程衝突,每個線程使用自己的TLAB,這樣就保證了不使用同步,提高了對象分配的效率。
TLAB本身佔用eden區空間,TLAB空間的內存非常小,缺省情況下僅佔有整個Eden空間的1%,由於TLAB空間一般不會很大,因此大對象無法在TLAB上進行分配,總是會直接分配在堆上。

方法區

方法區也是線程共享的區域,用於存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼、運行時常量池等。

運行時常量池:Class文件常量池(字面量和符號引用)種的內容在類加載後進入方法區種的運行時常量池中存放。(Class文件中除了包括類的版本、字段、方法、接口等描述信息外,還包括常量池)

哪些是Class文件常量池中的內容:

  • 字面量:文本字符串、被聲明爲final的常量值、基本數據類型的值等
  • 符號引用:類和接口的完全限定名、字段和名稱的描述符、方法名稱和描述符

參考:

  1. https://blog.csdn.net/Sugar_Rainbow/article/details/68150249
  2. https://www.jianshu.com/p/cf78e68e3a99

JVM棧

JVM棧是線程私有的,生命週期與線程相同。Java中的方法在執行時都會創建一個棧幀,用於存儲局部變量表,操作數棧,方法出口等信息,每一個方法的執行到完成的過程,就對應着一個棧幀在JVM棧中入棧到出棧的過程。如果線程請求的棧深度大於JVM所允許的深度時,就會拋出StackOverflowError異常。棧中保存的時基本數據類型的值和對象的引用地址,實際對象在堆中。

本地方法棧

功能與JVM棧相同,只不過JVM棧是爲JVM執行的方法(也就是字節碼)服務,而本地放發棧是爲JVM使用到的native方法(採用C、C++等其他語言實現)服務。

程序計數器

被看作當前線程所執行的字節碼的行號指示器,用來記錄當前線程正在執行的指令,是線程私有的。爲了線程切換後恢復到正確的位置繼續執行,所以每個線程都需要有一個獨立的程序計數器。如果執行的是native方法,這個計數器的值爲空。

參考:《深入理解Java虛擬機》

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