java性能優(yōu)化之分代回收
前言
我們今天一起來聊一聊關(guān)于垃圾收集的細(xì)節(jié)問題。垃圾收集是通過何種方式減少stop the world?這將是垃圾回收的重點(diǎn)內(nèi)容。
什么是分代回收?
什么是分代回收,初次接觸的同學(xué)肯定是很懵的。還記得我們前面在介紹使用jvisualvm工具的時(shí)候,從它給我們反饋的視圖上看到,有幾個(gè)不同的數(shù)據(jù)塊,且是動(dòng)態(tài)的,如下圖紅圈的部分:

從左到右分別是:
- Metaspace :元空間
- Old :老年代
- Eden + S0 + S1 : 這三個(gè)加在一起稱為年輕代
到目前為止,市面上常見的垃圾收集器,都是按照這種分代回收的方式進(jìn)行垃圾回收的,但是其內(nèi)部的實(shí)現(xiàn)方式卻有很大的差別。
本章我們的重點(diǎn)是 老年代 和 年輕代 。
通過上圖我們發(fā)現(xiàn),年輕代有三部分組成:
- Eden :通常稱為Eden區(qū),翻譯過來也可以稱為伊甸園區(qū)。
- S0 和 S1:通常稱為survivor區(qū),翻譯過來稱為幸存者區(qū),由幸存者0和幸存者1所組成。
為什么采用分代回收?
絕大部分的對(duì)象,它們的生命周期非常短暫,甚至絕大多數(shù)都是臨時(shí)對(duì)象,垃圾收集器的設(shè)計(jì)需要適應(yīng)這種情況。
我們都知道對(duì)象創(chuàng)建,存放在堆中,而不論是老年代還是年輕代都是堆中的一部分。
年輕代回收
當(dāng)對(duì)象被創(chuàng)建后,會(huì)被分配至年輕代,隨著對(duì)象的增加,年輕代會(huì)被占滿,此時(shí)將會(huì)停止全部的應(yīng)用線程,并進(jìn)行垃圾回收,沒有被使用的對(duì)象會(huì)被回收,仍然被使用的對(duì)象將會(huì)被移動(dòng)到其他的地方。這種操作就是MinorGC,年輕代回收。
使用分代算法的最根本原因,是為了盡量的減少垃圾回收造成的停頓,我們可以從下面兩個(gè)方面考慮:
- 新生代是堆的一部分,僅處理一部分空間,一定比整個(gè)堆空間的時(shí)間要短,停頓時(shí)間也就短。但是我們一定會(huì)想到,停頓的頻率增加了。
- 年輕代的空間分配方式,對(duì)性能有影響。年輕代中,eden占據(jù)大部分空間,而S0和S1平分剩余空間。對(duì)象首次創(chuàng)建會(huì)在Eden中,經(jīng)過一次垃圾回收時(shí),Eden被清空,未使用的對(duì)象被回收,仍然使用的對(duì)象進(jìn)入Survior或老年代。Eden區(qū)的清空操作,相當(dāng)于進(jìn)行了一次
壓縮整理。
即使是年輕代的回收,仍然存在時(shí)空停頓。
老年代回收
前面提到,除了在Eden可能將對(duì)象移動(dòng)到老年代當(dāng)中,對(duì)于在Survior當(dāng)中沒有被回收的對(duì)象,最終也會(huì)移動(dòng)到老年代當(dāng)中。當(dāng)老年代被占滿時(shí),會(huì)停止所有的應(yīng)用線程,找到不再使用的對(duì)象進(jìn)行垃圾回收。這個(gè)過程將會(huì)停頓很長時(shí)間,我們稱之為Full GC。
更加厲害的回收方式
前面的描述其實(shí)都是較為簡單的垃圾收集器,在停止應(yīng)用線程后去發(fā)現(xiàn)不再使用的對(duì)象,進(jìn)行回收。
然而實(shí)際上,通過一些定制,和復(fù)雜的計(jì)算,我們可以在應(yīng)用線程運(yùn)行時(shí)去找到不再使用的對(duì)象。在前一篇文章一筆帶過的CMS和G1收集器,就是如此。他們不需要停止應(yīng)用線程就可以找到不再使用的對(duì)象,所以它們也叫做concurrent垃圾收集器。
垃圾在查找的時(shí)候?qū)?huì)占用很多時(shí)間,當(dāng)然查找算法將是下一章節(jié)我們需要學(xué)習(xí)的內(nèi)容。然而concurrent垃圾收集器可以盡可能的減少應(yīng)用的停頓時(shí)間,它們也可以稱為低停頓收集器。
這種垃圾收集器縮減應(yīng)用的停頓時(shí)間,其代價(jià)是占用更多的CPU。即使是G1和CMS也會(huì)遇到長時(shí)間的Full GC,這將是我們需要針對(duì)實(shí)際環(huán)境調(diào)優(yōu)的方向。
垃圾收集器的權(quán)衡
前面簡單描述了不同垃圾收集器的垃圾收集方式,以及造成的影響。但是在我們選擇垃圾收集器的過程中還是需要一定的權(quán)衡,才能使其發(fā)揮最佳的性能。
我們需要考慮的重點(diǎn)就是:
吞吐量:如果你的系統(tǒng)需要大批量的處理數(shù)據(jù)等,換句話說,不要求每次響應(yīng)時(shí)間最快,而平均響應(yīng)時(shí)間更加重要,Parallel收集器也許會(huì)有不錯(cuò)的表現(xiàn)。響應(yīng)時(shí)間:簡單來說,如果你想要你的接口獲得更快的響應(yīng)時(shí)間,那么concurrent收集器將是更好的選擇。CPU性能:使用current收集器勢(shì)必要消耗更多的CPU資源。
到此這篇關(guān)于java性能優(yōu)化之分代回收的文章就介紹到這了,更多相關(guān)java性能優(yōu)化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Apache?Commons?Imaging處理圖像實(shí)例深究
這篇文章主要為大家介紹了Apache?Commons?Imaging處理圖像的實(shí)例探索深究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12
在Java內(nèi)存模型中測(cè)試并發(fā)程序代碼
這篇文章主要介紹了在Java內(nèi)存模型中測(cè)試并發(fā)程序代碼,輔以文中所提到的JavaScript庫JCStress進(jìn)行,需要的朋友可以參考下2015-07-07

