1. 程式人生 > >JVM的垃圾收集機制和記憶體分配策略

JVM的垃圾收集機制和記憶體分配策略

首先給大家看一下JVM的資料區模型。


上圖是JVM的資料區模型。但是在Hotspot JVM中,我們知道執行時常量是屬於方法區的,而方法區又屬於堆。對於棧,在hotspot中虛擬機器棧和本地棧是合二為一的。

這裡在順便說一說虛擬機器物件的結構,如下圖所示


這裡在提一提物件的引用問題:

Java是按值傳遞的,Java不存在引用傳遞。所謂的棧上的引用是用來操作堆上的具體的物件。但是這些引用實際上是這些具體物件在堆上的絕對地址的值。


接下來說說垃圾回收機制。通常我們所說的垃圾回收主要是針對堆的空間的。我們知道Java中的物件和陣列的建立都是在堆上完成的。當存在不需要的物件或者當有物件遊離時(

object=null)時,或者JVM的記憶體資源緊張時,JVM都會考慮進行垃圾回收。

堆的分配是按物件存活的時間分為新生代和老年代。具體如下圖所示:


堆記憶體是這樣分配的,有新生代和老年代之分。新生代又分為Eden區、To survivor區和From surivivor區。它們的比例的大小是811。在新生代中Eden區和To survivor區負責儲存new出來的物件。當儲存的物件過多時,JVM會進行垃圾回收。垃圾回收的機制是一種叫可達性的演算法。在確定了要清理的物件後,接下來主要分為兩部分:標記-清理、和停止複製。JVM首先會在Eden

區和To survivor區進行標記-清理動作。這將會清理掉部分的垃圾。對於那些存活的物件,會被複制到From survivor區域中。

如果當Eden區和兩個survivor區都塊用完的時候,這時候在進行可達性演算法的垃圾回收時,我們會將存活時間較長的物件複製到老年代中進行儲存。至於存活時間的閾值我們可以在通過虛擬機器引數 -XX:MaxTenuringThreshold來設定的。這有點像擔保機制一樣,老子為兒子的借款做擔保。如果兒子無力償還就由老子來還。(這就是記憶體的擔保機制)

當然了,對於哪些較大的物件。而且生命週期很長的物件。我們是直接將他們儲存在老年代中。在老年代中,進行垃圾回收的時候也是使用可達性演算法的。在確定了要清理的物件後,就開始進行標記-

清除,但這樣會出現許多記憶體碎片,於是接下來的動作就是複製。


最後來說說JVM的垃圾回收器。一共有7種垃圾回收器。如下圖所示:


Serial:單執行緒的,回收新生代的垃圾回收器。它是虛擬機器執行在Client模式下的預設新生代垃圾回收器。

Serial old:Serial是對應的,主要回收老年代的垃圾。

ParNew:主要就是Serial的多執行緒版。

Parallel新生代收集器,:它是併發的多執行緒收集器,主要使用的是複製的演算法。它主要是受一個可控制的吞吐量的影響。所謂的吞吐量就是CPU執行使用者程式碼的時間和CPU的總的消耗時間的比值。

Parallel Old:Parallel相對應,主要回收老年代的垃圾。

CMS:是一種以獲取最短的回收停頓時間為目標的收集器。目前主要用於大部分的Java應用集中在網際網路站和B/S系統服務中。

G1:是一個面向伺服器端應用的垃圾收集器。它是即可回收新生代也可以回收老年代。