天天看點

java gc回收的是堆記憶體嗎,JVM堆記憶體與垃圾回收

JVM堆記憶體與垃圾回收

2019-11-15 16:30:56.0

JVM堆記憶體

JVM堆記憶體結構

java gc回收的是堆記憶體嗎,JVM堆記憶體與垃圾回收

JVM堆記憶體配置設定和記憶體回收過程

年輕代的比例可以是:8:1:1;年輕代和老年代的比例可以是:1:3

新生對象配置設定在eden區,超過eden區大小的大對象,直接配置設定在老年代;

新生對象占滿eden區之後,繼續配置設定時,則會觸發GC(monitor GC或young GC,複制算法、可用并行垃圾回收器),将存活的對象放入s0區。同樣的過程之後,下次young GC被觸發時,将所有存活的對象複制在s1區。

新生代的垃圾回收比較頻繁,對象存活率低,是以使用複制算法,吧存活對象在s0和s1區反複複制,直到對象的存活年齡超過一定的門檻值,就會放入老年代。

是以,老年代存放的對象一般都是經過多次都沒被回收的,如果進行GC,對象的存活率比較高。

當老年代的空間不夠用時,會觸發Full GC/Major GC, Full GC使用标記-整理算法,可用串行垃圾收集器,會stop the world,是以盡量避免頻繁執行Full GC。

垃圾回收算法

複制算法

将存活對象複制到一塊新的記憶體區域即可。eg:新生代垃圾回收時,将eden區和s0區存活的對象複制到s1區。

标記-整理算法

将存活對象标記,然後移動到記憶體區域的一端。

對象存活的判斷

引用計數

每次引用一個對象,就計數加1,計數為0時,就成為垃圾。這個方法無法解決循環引用的問題。

可達性分析

GC root 可以到達的對象都為存活對象。

可以作為GC Roots的對象包括:

虛拟機棧中引用的對象(局部變量)

方法區中類靜态屬性引用的對象(靜态變量)

方法區中常量引用的對象(常量)

本地方法棧中JNI(即本地方法)引用的對象

垃圾回收器

java gc回收的是堆記憶體嗎,JVM堆記憶體與垃圾回收

新生代

工作區域線程數垃圾收集算法Serial收集器新生代單線程複制算法Client模式下的預設新生代收集器。進行垃圾收集時,必須Stop the world,直到它收集結束。-XX:+UseSerialGC

ParNew收集器(Serial收集器的多線程版本)新生代多線程複制算法Server模式下的預設新生代收集器

Parallel Scavenge收集器新生代多線程複制算法吞吐量優先收集器目标:控制吞吐量吞吐量=運作使用者代碼時間/(運作使用者代碼時間+垃圾收集時間)吞吐量越高說明CPU時間使用率越高。JVM參數:-XX:MaxGCPauseMillis 控制最大垃圾收集時間-XX:GCTimeRatio 控制吞吐量大小-XX:+UseParallelGC -XX:+UseParallelOldGC

老年代

作用區域單線程/多線程垃圾收集算法Serial Old收集器(Stop the World)老年代單線程标記整理算法這個收集器的主要意義也是在于給Client模式下的虛拟機使用。 如果在Server模式下,主要兩大用途:(1)在JDK1.5以及之前的版本中與Parallel Scavenge收集器搭配使用(2)作為CMS收集器的後備預案,在并發收集發生Concurrent Mode Failure時使用

Parallel Old收集器(Stop the World)老年代多線程标記整理算法Parallel Old 是Parallel Scavenge收集器的老年代版本。這個收集器在1.6中才開始提供。在JDK1.5以及之前的版本中,Parallel Scavenge+Serial Old(單線程),無法充分利用多CPU的處理能力。1.6之後,終于有了名副其實的“吞吐量優先“收集器組合:Parallel Scavenge + Parallel Old。

CMS收集器(Concurrent Mark Sweep)老年代多線程标記-清除算法目标:最短回收停頓時間優點:并發收集,低停頓缺點:1)CPU資源敏感。在并發階段,雖然不會導緻用于線程停頓。但會因為占用了一部分CPU資源,導緻使用者應用程式變慢,吞吐量降低。2)無法處理浮動垃圾并發清理階段,使用者線程仍舊在運作并産生垃圾,這些産生的垃圾此次收集無法清理。是以,需要預留一部分記憶體用于并發清理時使用者程式使用。解決方法:當預留的記憶體不夠時,将發生Concurrent Mode Failure,JVM啟動後備預案,臨時啟用Serial Old進行老年代垃圾收集-XX:CMSInitiatingOccupancyFraction3)記憶體碎片問題解決方法:-XX:CMSFullGCsBeforeCompaction 設定執行多少次不帶壓縮的Full GC後,運作一次帶壓縮的(預設為0,表示每次Full GC都進行碎片整理)

G1垃圾收集

java gc回收的是堆記憶體嗎,JVM堆記憶體與垃圾回收

G1垃圾收集器

G1收集器将java堆均分成大小相同的區域(region,1M-32M,最多2000個,最大支援堆記憶體64G)。一個或多個不連續的區域共同組成eden、survivor或old區,但大小不再固定,這為記憶體應用提供了極大地彈性。G1垃圾收集過程與CMS類似。G1在堆記憶體中并發地對所有對象進行标記,決定對象的可達性。經過全局标記,G1了解哪些區域幾乎是空的,然後優先收集這些區域,這就是GarbageFirst的命名由來。G1将垃圾收集和記憶體整理活動專注于那些幾乎全是垃圾的區域,并建立停頓預測模型來決定每次GC時回收哪些區域,以滿足使用者設定的停頓時間。

對于區域的回收通過複制算法實作。在完成标記清理後,G1将這幾個區域的存活對象複制到一個單獨區域中,實作記憶體整理和空間釋放。這一過程通過多線程并行進行來降低停頓時間,提高吞吐量。通過這樣的方式,G1在每次GC過程中持續清理碎片,控制停頓時間滿足使用者要求。這時過去虛拟機無法做到的。CMS不清理記憶體碎片(除非通過虛拟機參數設定,在每次或多次FullGC後進行整理),ParallelOld進行全堆整理,會導緻較長的停頓時間。

G1不是實時垃圾收集器,它會盡量讓停頓時間低于使用者設定的停頓時間目标但不能保證一定如此。G1根據曆史垃圾收集監測資料來 預測每個區域的回收時間,然後根據使用者設定的目标停頓時間決定每次GC時可以回收哪些區域。G1通過這種方式建立比較精确的區域回收時間預測模型。

G1垃圾收集器的模式

region

java -XX:G1HeapRegionSize=2M

1M、2M、4M、8M、16M、32M

young gc

如上圖中,eden regions中沒有足夠空間時,觸發young gc:将存活的對象複制到s regions或者old regions當中

mixed gc

當老年代old regions的大小占比達到一個門檻值時,會觸發mixed gc:回收所有年輕代regions和一部分老年代的regions。

full gc

當老年代的regions沒有足夠空間時,就會觸發full gc:單線程回收老年代,暫停時間較長,需要盡量避免。

G1垃圾收集器的特點

可并行收集,充分利用cpu多核的資源

分代回收,不同代使用不同的回收算法

碎片整理(CMS不進行整理:标記-清除)

回收時間預測,預測每個region回收的時間,根據目标停頓時間對region進行選擇性回收

ZGC垃圾回收

不論堆記憶體大小,都能保持低于10ms的停頓。把堆分成不同大小的region,回收時不進行分代。标記後,選擇存活對象較少的region,将其中的存活對象複制到新的region中即可。

java gc回收的是堆記憶體嗎,JVM堆記憶體與垃圾回收
java gc回收的是堆記憶體嗎,JVM堆記憶體與垃圾回收
java gc回收的是堆記憶體嗎,JVM堆記憶體與垃圾回收

JVM垃圾收集器總結

Serial 串行收集器:單線程執行、停頓時間較長,一般用于client模式

java -XX:+UseSerialGC

Parallel 并行收集器:多線程執行、停頓時間短,一般用于server模式

java -XX:+UseParallelGC -XX:ParallelGCThreads=4

複制算法:效率較高,适合于頻繁的收集,不過占用記憶體較大,需要兩倍。是以多用于年輕代的回收

标記-整理算法:效率較低,整理記憶體碎片。一般用在老年代,因為老年代不需要頻繁收集

标記-清除算法:效率較高,不整理碎片。CMS收集器中使用這種算法

CMS垃圾收集器:使用标記-清除算法,在多次Full GC後會進行一次整理。會預留一部分記憶體用于并發清理時使用者程式配置設定使用,如果這部分不夠用,則啟用單線程串行進行收集,是以收集的時間無法預測,時間差異較大。

G1垃圾收集器:分成大小相等的region,優先收集垃圾較多的region。可預測每個region的收集時間。

java -XX:+UseG1GC

ZGC收集器:不論堆記憶體大小,都保持低于10ms的停頓,把堆分成不同大小的region,回收時不進行分代。

2019-11-15 16:30:56.0