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