date: 2020-03-18
本文參考自網(wǎng)絡(luò)上多篇博客,并個人歸納總結(jié),故此處不一一列舉。
主要對一種 JVM 進行概況。
Garbage Collection (垃圾回收機制)
GC 主要分為 Minor GC 和 Major GC,它們又被稱為 Young GC 和 Full GC。前者主要針對 Heap 中的 Young Gen,而后者針對 Young Gen 和 Old Gen 等區(qū)域。
在每一次 GC 之后,在此次 GC 中存活的對象 age 加 1,age 過大時對象會進入 Old Gen。
Heap(堆)
Heap 區(qū)域線程共享,它是 GC 的重點管理對象,其分為 Young Gen 和 Old Gen。其中 Young Gen 存放存活時間較短和較小的對象,Old Gen 則存放存活時間較長或者較大的對象。(注意“和”與“或”的用法)
Young Gen (新生代)
Young Gen 分為 Eden Space (伊甸園) 和 Survivor Space (幸存者區(qū))。Eden Space 存放新創(chuàng)建的對象,并在 GC 后將所有未被回收的對象移至 Survivor Space 中的 To Survivor 區(qū)域中。
Survivor Space 劃分為兩個等大的區(qū)域:To Survivor 和 From Survivor。From Survivor 存放未被回收且未被移至 Old Gen 的對象,在 GC 之后將剩余的所有未被回收的對象移至 To Survivor 中。而 To Survivor 在 GC 之前一直保持 empty,在 GC 之后存放來自 Eden Space 和 From Survivor 的未被回收的對象。最后 To Survivor 和 From Survivor 會互換標識,這樣使得相應(yīng)標識的區(qū)域一直保持相同的功能,即使它的內(nèi)存區(qū)域一直在變化。
Old Gen (老年代)
Old Gen 中存放的是 Young Gen 中經(jīng)過多次垃圾回收仍然存活的對象和 Young Gen 分配不了內(nèi)存的大對象。在 Old Gen 存放滿之后會觸發(fā) JVM 進行 Major GC。
個人認為這樣設(shè)計的原因是,Minor GC 對運算資源的消耗比較少,所以可以通過多次的 Minor GC 盡可能地回收不需要的內(nèi)存空間,節(jié)約內(nèi)存資源。而經(jīng)過多次 Minor GC 依舊存活的對象可能在未來很長一段時間內(nèi)都不會被回收,所以就將其移入 Old Gen 中,等待 Old Gen 滿時進行一次大規(guī)模的內(nèi)存回收,避免其一直在 Young Gen 內(nèi)增加 Minor GC 執(zhí)行時所需的運算資源。
Method Area (方法區(qū))
Method Area 線程共享,它一般存放類的信息、常量、靜態(tài)變量、即時編譯器編譯的代碼等。其中常量存放在 Runtime Constant Pool (運行時常量池) 中。
以前它是位于 Perm Gen (永久代) 中,但現(xiàn)在 Perm Gen 已經(jīng)被逐漸拆分并取代,取而代之的是 Meta Space (元空間)。
PC Register (程序計數(shù)器)
PC Register 線程私有,用于執(zhí)行一個 Java Method 時記錄正在執(zhí)行的虛擬機字節(jié)碼指令的地址,在執(zhí)行 Native Method 時它的值為 undefined。它是 JVM 中最小的一塊內(nèi)存區(qū)域,也是唯一一個在 Java 虛擬機規(guī)范中沒有規(guī)定任何 OutOfMemoryError 情況的區(qū)域。
JVM Stack (Java虛擬機棧)
JVM Stack 線程私有,它的生命周期和線程一致。
Java 方法在執(zhí)行時會在 JVM Stack 中入棧一個 Stack Frame (棧幀),方法結(jié)束時出棧。這個棧幀中存放著以下數(shù)據(jù):
-
Local Variable Table(局部變量表)- 各種基本類型
- 對象引用
Return Address
-
Operand Stack(操作數(shù)棧) -
Dynamic Linking(動態(tài)鏈接) -
Return Address(返回地址) -
Stack Data(幀數(shù)據(jù)區(qū))
同時它會在線程請求的棧深度大于虛擬機所允許的深度時會出現(xiàn) StackOverflowError,而在 JVM Stack 可以動態(tài)擴展,但擴展時無法申請到足夠的內(nèi)存時出現(xiàn) OutOfMemoryError。
Native Method Stack (本地方法棧)
類似 JVM Stack,同樣是線程私有的。但它服務(wù)于 Native Method,同時也具有 StackOverflowError 和 OutOfMemoryError。
Meta Space (元空間)
使用本地內(nèi)存,其取代 Perm Gen (永久代) 存放類相關(guān)的元數(shù)據(jù)。
直接內(nèi)存
它通過調(diào)用本地方法直接分配 JVM 之外的內(nèi)存,可以通過 DirectByteBuffer 對象直接操作該內(nèi)存,同時存在 OutOfMemoryError。