導航:首頁 > 萬維百科 > g1收集器和cms

g1收集器和cms

發布時間:2020-09-02 16:20:19

1、G1會成為新的默認垃圾收集器嗎?

Java只有一個垃圾收集器,而事實上它有4個。Java9中,仍有一個運行提議,關於替換由Java7引入的G1默認垃圾收集器(並行/吞吐量收集)的討論。
通常來說,G1被設計來更好地支持大於4GB的堆,並且不會造成頻繁的GC暫停,但當暫停發生時,往往會處理更長時間。

2、jvm垃圾收集器為什麼

JVM中垃圾的回收由垃圾收集器進行,隨著JDK的不斷升級,垃圾收集器也開發出了各種版本,垃圾收集器不斷優化的動力,就是為了實現更短的停頓。

下面是7種不同的分代收集器,如果兩個收集器之間有連線,則表示它們之間可以搭配使用;所處的區域表示屬於新生代還是老年代收集器。

1.Serial 收集器 (新生代)

最基本、歷史最悠久(JDK1.3.1之前),這是一個單線程的收集器,當該收集器運行時必須暫停其他所有的工作線程,直到它收集結束。

收集過程:暫停所有線程

演算法:復制演算法

優點:簡單高效,擁有很高的單線程收集效率

應用:Client模式下的默認新生代收集器

2.ParNew 收集器 (新生代)

Serial 的多線程版本,使用多線程進行垃圾收集

收集過程:與用戶線程並發

演算法:復制演算法

優點:在CPU多的情況下,擁有比Serial更好的效果。單CPU環境下Serial效果更好

應用:許多運行在Server模式下的虛擬機中首選的新生代收集器

3.Parallel Scavenge 收集器(新生代)

Parallel Scavenge收集器的目標是達到一個可控制的吞吐量

吞吐量 = 運行用戶代碼時間 / (運行用戶代碼時間 + 垃圾收集時間)

控制吞吐量的參數:最大垃圾收集停頓時間 -XX:MaxGCPauseMillis ; 直接設置吞吐量大小:-XX:GCTimeRatio。

MaxGCPauseMillis 的值為一個大於0的毫秒數, 最大停頓時間的縮短是以犧牲吞吐量和新生代空間來換取的。

GCTimeRatio 的值為一個大於0且小於100的整數。例如:-XX:GCTimeRatio=9 我們要求應用程序線程在整個執行時間中至少9/10是活動的(因此,GC線程佔用其餘1/10)

-XX:+UseAdaptiveSizePolicy:開啟GC自適應調節策略,自動設置新生代大小、Eden與Survior區的比例、晉升老年代對象年齡等細節參數

應用:適合在後台運算而不需要太多交互的任務

4.Serial Old 收集器 (老年代)

Serial收集器的老年代版本,也是一個單線程的收集器,使用標記-整理演算法

收集過程:暫停所有線程

演算法:標記-整理演算法

應用:主要意義是Client模式下的收集器,如果在Server模式下還有:a. JDK1.5之前的版本中與Parallel Scavenge搭配使用,b. 作為CMS收集器的後背預案在並發收集時使用

5. Parallel Old 收集器 (老年代)

Parallel Scavenge收集器的老年代版本,使用多線程和「標記-整理」演算法。

收集過程:多線程

演算法:標記-整理演算法

應用:在注重吞吐量及CPU資源敏感的場合,可以優先考慮Parallel Scavenge加Parallel Old收集器

6. CMS 收集器 (老年代)

以獲取最短回收停頓時間為目標,基於「標記-清除」演算法

收集過程:初始標記-->並發標記-->重新標記-->並發清除

初始標記、重新標記兩個步驟仍需要「Stop The World」 : 初始標記僅僅只是標記一下GC
Roots能直接關聯到的對象,速度很快;並發標記就是進行GC Roots
Tracing的過程;重新標記是為了修正並發標記期間因用戶程序繼續運作,而導致標記產生變動的那一部分對象的標記記錄。

整個過程中耗時最長的是並發標記和並發清除,這兩個過程都可以與用戶線程一起工作。所以總體上說CMS收集器內存回收過程與用戶線程一起並發執行。

演算法:標記-清除 演算法

缺點:1,對cpu資源敏感,默認啟動的回收線程數是(cpu數量+3)/4,當cpu數較少的時候,會分掉大部分的cpu去執行收集器線程,影響用戶,降低吞吐量。

2,無法處理浮動垃圾,浮動垃圾即在並發清除階段因為是並發執行,還會產生垃圾,這一部分垃圾即為浮動垃圾,要等下次收集。

3,因為使用的是「標記-清除」演算法,會產生碎片。

7. G1收集器 (整個Java堆:包括新生代和老年代)

特點:並行與並發、分代收集、空間整合、可預測的停頓

G1將整個java堆(包括新生代和老生代)劃分為多個大小固定的獨立區域,並跟蹤這些區域的垃圾堆積程度,在後台維護一個優先列表,每次根據允許的收集時間,優先回收垃圾最多的區域。

但這樣回收有一個問題:對象分配在某個區域中,但並非只被本區域的其他對象引用,而是可以與整個Java堆任意的對象發生引用關系。在做可達性分析的時候,如何避免掃描整個堆呢?

解決:區域之間的對象引用,以及其他收集器中新生代與老年代之間的對象引用,虛擬機都是使用Remembered Set來避免全堆掃描,在Remembered Set中記錄對象的引用。

收集過程:初始標記-->並發標記-->最終標記-->篩選回收。與CMS不同的是,在最終標記階段,需要停頓線程,但是可並發執行;篩選回收階段,對各個區域的回收價值和成本進行排序,按照用戶所期望的回收時間進行垃圾回收,這個階段也可以並發執行。

3、HotSpot JVM支持哪些垃圾收集器

按線程
單線程:Serial、SerialOld
多線程:ParNew、Parallel Scavenge、Parallel Old、CMS、G1

按適用代
新生代: Serial、ParNew、Parallel Scavenge
老年代: SerialOld、CMS 、Parallel Old
G1可以在新生代和老年代使用

常見的組合
ParNew+CMS
Parallel Scavenge+Parallel Old

4、JVM的垃圾演算法有哪幾種

一、垃圾收集器概述

如上圖所示,垃圾回收演算法一共有7個,3個屬於年輕代、三個屬於年老代,G1屬於橫跨年輕代和年老代的演算法。

JVM會從年輕代和年老代各選出一個演算法進行組合,連線表示哪些演算法可以組合使用

二、各個垃圾收集器說明

1、Serial(年輕代)

年輕代收集器,可以和Serial Old、CMS組合使用

採用復制演算法

使用單線程進行垃圾回收,回收時會導致Stop The World,用戶進程停止

client模式年輕代默認演算法

GC日誌關鍵字:DefNew(Default New Generation)

圖示(Serial+Serial Old)

2、ParNew(年輕代)

新生代收集器,可以和Serial Old、CMS組合使用

採用復制演算法

使用多線程進行垃圾回收,回收時會導致Stop The World,其它策略和Serial一樣

server模式年輕代默認演算法

使用-XX:ParallelGCthreads參數來限制垃圾回收的線程數

GC日誌關鍵字:ParNew(Parallel New Generation)

圖示(ParNew + Serail Old)

3、Paralle Scavenge(年輕代)

新生代收集器,可以和Serial Old、Parallel組合使用,不能和CMS組合使用

採用復制演算法

使用多線程進行垃圾回收,回收時會導致Stop The World

關注系統吞吐量

-XX:MaxGCPauseMillis:設置大於0的毫秒數,收集器盡可能在該時間內完成垃圾回收

-XX:GCTimeRatio:大於0小於100的整數,即垃圾回收時間占總時間的比率,設置越小則希望垃圾回收所佔時間越小,CPU能花更多的時間進行系統操作,提高吞吐量

-XX:UseAdaptiveSizePolicy:參數開關,啟動後系統動態自適應調節各參數,如-Xmn、-XX:SurvivorRatio等參數,這是和ParNew收集器重要的區別

GC日誌關鍵字:PSYoungGen

4、Serial Old(年老代)

年老代收集器,可以和所有的年輕代收集器組合使用(Serial收集器的年老代版本)

採用 」標記-整理「演算法,會對垃圾回收導致的內存碎片進行整理

使用單線程進行垃圾回收,回收時會導致Stop The World,用戶進程停止

GC日誌關鍵字:Tenured

圖示(Serial+Serial Old)

5、Parallel Old(年老代)

年老代收集器,只能和Parallel Scavenge組合使用(Parallel Scavenge收集器的年老代版本)

採用 」標記-整理「演算法,會對垃圾回收導致的內存碎片進行整理

關注吞吐量的系統可以將Parallel Scavenge+Parallel Old組合使用

GC日誌關鍵字:ParOldGen

圖示(Parallel Scavenge+Parallel Old)

6、CMS(Concurrent Mark Sweep年老代)

年老代收集器,可以和Serial、ParNew組合使用

採用 」標記-清除「演算法,可以通過設置參數在垃圾回收時進行內存碎片的整理
1、:默認開啟,FullGC時進行內存碎片整理,整理時用戶進程需停止,即發生Stop The World
2、CMSFullGCsBeforeCompaction:設置執行多少次不壓縮的Full GC後,執行一個帶壓縮的(默認為0,表示每次進入Full GC時都進行碎片整理)

CMS是並發演算法,表示垃圾回收和用戶進行同時進行,但是不是所有階段都同時進行,在初始標記、重新標記階段還是需要Stop the World。CMS垃圾回收分這四個階段
1、初始標記(CMS Initial mark)  Stop the World 僅僅標記一下GC Roots能直接關聯到的對象,速度快
2、並發標記(CMS concurrent mark) 進行GC Roots Tracing,時間長,不發生用戶進程停頓
3、重新標記(CMS remark)  Stop the World 修正並發標記期間因用戶程序繼續運行導致標記變動的那一部分對象的標記記錄,停頓時間較長,但遠比並發標記時間短
4、並發清除(CMS concurrent sweep) 清除的同時用戶進程會導致新的垃圾,時間長,不發生用戶進程停頓

適合於對響應時間要求高的系統

GC日誌關鍵字:CMS-initial-mark、CMS-concurrent-mark-start、CMS-concurrent-mark、CMS-concurrent-preclean-start、CMS-concurrent-preclean、CMS-concurrent-sweep、CMS-concurrent-reset等等

缺點
1、對CPU資源非常敏感
2、CMS收集器無法處理浮動垃圾,即清除時用戶進程同時產生的垃圾,只能等到下次GC時回收
3、因為是使用「標記-清除」演算法,所以會產生大量碎片

圖示

7、G1

G1收集器由於沒有使用過,所以從網上找了一些教程供大家了解

並行與並發

分代收集

空間整合

可預測的停頓

5、ParNew 和 PSYoungGen 和 DefNew 是一個東西么?

查了一下書:是這樣的。串列收集器:DefNew:是使用-XX:+UseSerialGC(新生代,老年代都使用串列回收收集器)。並行收集器:ParNew:是使用-XX:+UseParNewGC(新生代使用並行收集器,老年代使用串列回收收集器)或者-XX:+UseConcMarkSweepGC(新生代使用並行收集器,老年代使用CMS)。PSYoungGen:是使用-XX:+UseParallelOldGC(新生代,老年代都使用並行回收收集器)或者-XX:+UseParallelGC(新生代使用並行回收收集器,老年代使用串列收集器)garbage-first heap:是使用-XX:+UseG1GC(G1收集器)

6、生產中 java 垃圾回收為什麼不用g1

垃圾回收是Java語言的一大特性,方便了編程,是以消耗性能為代價的,Java語言對內存的分配管理是通過JVM內部機制決定的。
Java虛擬機中有個稱之為垃圾回收器的東西,實際上這個東西也許真正不存在,或者是已經集成到JVM中了,但這無關緊要,仍然可以稱為為垃圾回收器。
垃圾回收器的作用是查找和回收(清理)無用的對象。以便讓JVM更有效的使用內存。
垃圾回收器的運行時間是不確定的,由JVM決定,在運行時是間歇執行的。雖然可以通過System.gc()來強制回收垃圾,但是這個命令下達後無法保證JVM會立即響應執行,但經驗表明,下達命令後,會在短期內執行你的請求。JVM通常會感到內存緊缺時候去執行垃圾回收操作。
垃圾回收過於頻繁會導致性能下降,過於稀疏會導致內存緊缺。這個JVM會將其控制到最好,不用程序員擔心。但有些程序在短期會吃掉大量內存,而這些恐怖的對象很快使用結束了,這時候也許有必要強制下達一條垃圾回命令,這是很有必要的,以便有更多可用的物理內存。
垃圾回收器僅僅能做的是盡可能保證可用內存的使用效率,讓可用內存得到高效的管理。程序員可以影響垃圾回收的執行,但不能控制。
總之,在Java語言中,判斷一塊內存空間是否符合垃圾收集器收集標準的標准只有兩個:
1.給對象賦予了空值null,以下再沒有調用過。
2.給對象賦予了新值,既重新分配了內存空間。

7、g1回收器和其他回收器有什麼區別

1

8、提高Java性能的幾個高效用法

1.循環

■ 在重要的循環里,消除循環終止判斷時的方法調用。。。
例如:將...

for( int i = 0; i < collection.size(); i++){
...
}

替換為…

for( int i = 0; n = collection.size(); i < n; i++){
...
}

通常,把與循環index不相關的移到循環的外面

for( int i = 0; terminal = x.length; i < terminal; i++){
X[i] = x[i] / scaleA * scaleB
}

應該該成:

Double scale = scaleb / scaleA;
for( int i = 0; terminal = x.length; i < terminal; i++){
X[i] = x[i] * scale
}

2.字元串

■ 消除字元串連接
■ 創建長字元串時,總是使用StringBuffter代替String
■ 預先分配StringBuffer空間
StringBuffer sb = new StringBuffer(5000);

3.基本數據類型

■ 在重要的循環里使用基本數據類型(int型數據通常比long/double型數據更快)
■ 基本數據類型(Boolean,Integer,etc)的包裝類主要用在當傳遞的方法參數必須是一個對象的引用時(而不是一個基本數據類型)
■ 對所有的常量代數表達式使用static final修飾符
一 使常量更容易引用(編譯器預先計算常量表達式)

4.異常

■ 異常只用於單個真正的錯誤條件
一 拋出一個異常和執行一個catch代碼塊花費是很高的(主要由於當創建一個異常時要獲得線程棧的一個快照)
一 只當條件真的異常時才拋出一個異常
■ 使編譯器和運行時最優化,將幾個方法調用放在一個try/catch塊中,而不是為每個方法調用實現幾個try/catch塊

try{
Some.method1(); //Difficut for javac
} catch (method1Exception e) { //and the JVM runtime
//Handle exception 1// to optimixe this code
}

try{
Some.method2();
} catch (method2Exception e) {
// Handle exception 2
}

try{
Some.method3();
} catch (method3Exception e) {
// Handle exception 3
}

try{
Some.method1();
Some.method2();
Some.method3(); // easier to optimize
} catch (method1Exception e) {
// Handle exception 1
} catch (method2Exception e) {
// Handle exception 2
} catch (method3Exception e) {
// Handle exception 3
}

5.基準

■ 注意,所有這些技巧會因不同的平台和虛擬機而不同
一 例如:在有些servlet容器內,通過一個OutputStream作為位元組輸出會更快
一 在其它的容器內,通過一個PrintWriter輸出字元會更快
■ 這些技巧描述的是最可移植的建議
■ 你可能需要運行一些基準來判斷在你的平台上怎麼樣是最快的

9、java虛擬機常見的幾種垃圾收集演算法

1、垃圾收集器概述
垃圾收集器是垃圾回收演算法(標記-清除演算法、復制演算法、標記-整理演算法、火車演算法)的具體實現,不同商家、不同版本的JVM所提供的垃圾收集器可能會有很在差別,本文主要介紹HotSpot虛擬機中的垃圾收集器。
1-1、垃圾收集器組合
JDK7/8後,HotSpot虛擬機所有收集器及組合(連線),如下圖:
(A)、圖中展示了7種不同分代的收集器:
Serial、ParNew、Parallel Scavenge、Serial Old、Parallel Old、CMS、G1;
(B)、而它們所處區域,則表明其是屬於新生代收集器還是老年代收集器:
新生代收集器:Serial、ParNew、Parallel Scavenge;
老年代收集器:Serial Old、Parallel Old、CMS;
整堆收集器:G1;
(C)、兩個收集器間有連線,表明它們可以搭配使用:
Serial/Serial Old、Serial/CMS、ParNew/Serial Old、ParNew/CMS、Parallel Scavenge/Serial Old、Parallel Scavenge/Parallel Old、G1;
(D)、其中Serial Old作為CMS出現"Concurrent Mode Failure"失敗的後備預案(後面介紹);
1-2、並發垃圾收集和並行垃圾收集的區別
(A)、並行(Parallel)
指多條垃圾收集線程並行工作,但此時用戶線程仍然處於等待狀態;
如ParNew、Parallel Scavenge、Parallel Old;
(B)、並發(Concurrent)
指用戶線程與垃圾收集線程同時執行(但不一定是並行的,可能會交替執行);
用戶程序在繼續運行,而垃圾收集程序線程運行於另一個CPU上;
如CMS、G1(也有並行);
1-3、Minor GC和Full GC的區別
(A)、Minor GC
又稱新生代GC,指發生在新生代的垃圾收集動作;
因為Java對象大多是朝生夕滅,所以Minor GC非常頻繁,一般回收速度也比較快;
(B)、Full GC
又稱Major GC或老年代GC,指發生在老年代的GC;
出現Full GC經常會伴隨至少一次的Minor GC(不是絕對,Parallel Sacvenge收集器就可以選擇設置Major GC策略);
Major GC速度一般比Minor GC慢10倍以上;

與g1收集器和cms相關的知識