1. 程式人生 > >JVM垃圾收集器組合--各種組合對應的虛擬機器引數實踐

JVM垃圾收集器組合--各種組合對應的虛擬機器引數實踐

前言

相信很多人都看過下面這張圖,(來自《深入理解Java虛擬機器:JVM高階特性與最佳實踐》)

 

 

在學完幾種垃圾收集器型別及組合後,打算看看實際中程式用到的垃圾收集器。

但是在jconsole中看到的,如下:

 

 兩邊的名稱並不完全匹配,給我造成了很多困惑之處。

實際上,jconsole裡面用到的,我想應該是JVM內部使用到的名字。

 

本文主要講解新生代、老年代可用的垃圾收集器,如何檢視執行中程式使用的垃圾收集器,可用的垃圾收集器組合及對應引數配置等。

資料來源於:

1、《深入理解Java虛擬機器:JVM高階特性與最佳實踐》

2、http://www.fasterj.com/articles/oraclecollectors1.shtml

 

一、垃圾收集器

1.新生代

1.1 Copy(別名:Serial、DefNew) 

-the serial copy collector, uses one thread to copy surviving objects from Eden to Survivor spaces and between Survivor spaces until it decides they've been there long enough, at which point it copies them into the old generation.

譯文:Serial垃圾收集器,使用單執行緒完成下列工作:

從Eden區和From Survivor區拷貝存活物件到To Survivor區域、當存活物件在Survivor區超過年齡閾值時,拷貝到老年代。

這裡的名稱為Copy,實際上就是上圖的Serial收集器。

1.2 PS Scavenge(別名:Parallel Scavenge、PSYoungGen)

-the parallel scavenge collector, like the Copy collector, but uses multiple threads in parallel and has some knowledge of how the old generation is collected (essentially written to work with the serial and PS old gen collectors).

譯文:即Parallel Scavenge收集器,和Copy收集器類似,不過差別是它採用多執行緒進行並行收集。Parallel Scavenge收集器的目標則是達到一個可控制的吞吐量(Throughput) 。

Parallel Scavenge收集器提供了兩個引數用於精確控制吞吐量, 分別是控制最大垃圾收集停頓時間的-XX:MaxGCPauseMillis引數以及直接設定吞吐量大小的-XX: GCTimeRatio引數。由於與吞吐量關係密切, Parallel Scavenge收集器也經常稱為“吞吐量優先” 收集器。 除上述兩個引數之外, Parallel Scavenge收集器還有一個引數-XX: +UseAdaptiveSizePolicy值得關注。 這是一個開關引數, 當這個引數開啟之後,虛擬機器會根據當前系統的執行情況收集效能監控資訊, 動態調整這些引數以提供最合適的停頓時間或者最大的吞吐量, 這種調節方式稱為GC自適應的調節策略(GC Ergonomics) [1]。 

1.3 ParNew (別名和內部名一樣為ParNew)

-the parallel copy collector, like the Copy collector, but uses multiple threads in parallel and has an internal 'callback' that allows an old generation collector to operate on the objects it collects (really written to work with the concurrent collector).

ParNew收集器其實就是Serial收集器的多執行緒版本, 除了使用多條執行緒進行垃圾收集。

 

1.4 G1 Young Generation

-the garbage first collector, uses the 'Garbage First' algorithm which splits up the heap into lots of smaller spaces, but these are still separated into Eden and Survivor spaces in the young generation for G1.

 

2.老年代

2.1.MarkSweepCompact (別名:Serial Old(MSC))

 the serial mark-sweep collector, the daddy of them all, uses a serial (one thread) full mark-sweep garbage collection algorithm, with optional compaction.

Serial Old是Serial收集器的老年代版本, 它同樣是一個單執行緒收集器, 使用“標記-整理” 演算法。 

 

 2.2 PS MarkSweep(別名:Parallel Old

 the parallel scavenge mark-sweep collector, parallelised version (i.e. uses multiple threads) of the MarkSweepCompact.

Parallel Old是Parallel Scavenge收集器的老年代版本, 使用多執行緒和“標記-整理” 演算法。 

同樣,也是上面MarkSweepCompact 的多執行緒版本。

 

 2.3 ConcurrentMarkSweep (別名:CMS)

 the concurrent collector, a garbage collection algorithm that attempts to do most of the garbage collection work in the background without stopping application threads while it works (there are still phases where it has to stop application threads, but these phases are attempted to be kept to a minimum). Note if the concurrent collector fails to keep up with the garbage, it fails over to the serial MarkSweepCompact collector for (just) the next GC.

CMS(Concurrent Mark Sweep) 收集器是一種以獲取最短回收停頓時間為目標的收集器。

CMS收集器工作時,會在後臺完成大部分的垃圾收集工作而不停止使用者執行緒(停止使用者執行緒的階段依然存在,只是會被維持在很低的水平)

CMS執行期間可能失敗, 這時虛擬機器將啟動後備預案: 臨時啟用Serial Old(MarkSweepCompact )收集器來重新進行老年代的垃圾收集, 這樣停頓時間就很長了。 

 

2.4 G1 Mixed Generation

 the garbage first collector, uses the 'Garbage First' algorithm which splits up the heap into lots of smaller spaces.

 

3.總結

All of the garbage collection algorithms except ConcurrentMarkSweep are stop-the-world, i.e. they stop all application threads while they operate - the stop is known as 'pause' time. The ConcurrentMarkSweep tries to do most of it's work in the background and minimize the pause time, but it also has a stop-the-world phase and can fail into the MarkSweepCompact which is fully stop-the-world. (The G1 collector has a concurrent phase but is currently mostly stop-the-world).

 所有的垃圾回收演算法,除了ConcurrentMarkSweep外, 都會stop-the-world,比如他們在進行垃圾回收時,會停止所有的應用程式執行緒。ConcurrentMarkSweep 試圖在後臺進行大部分的工作,儘量把停頓時間削減到最小,但是它仍然會有stop-the-world階段。而且,當ConcurrentMarkSweep 收集失敗時,會回退到MarkSweepCompact演算法(該演算法會完全阻止應用程式的執行) 

 

以上只是簡單介紹,詳細可以參考書籍或者以下連結:

JVM-垃圾收集器

 

 

4.判斷當前正在使用的垃圾收集器

如果程式已經處於執行狀態,可使用jconsole、jinfo(linux下)檢視。

 

二、新生代老年代之間的收集器組合

That's the set of garbage collectors available, but they operate in two different heap spaces and it's the combination that is what we actually end up with for a particular JVM setting, so I'll also list the combinations that are possible. It doesn't explode into a dozen combinations because not all of these collectors work with each other. G1 is effectively an antisocial collector that doesn't like working with anyone else; the serial collectors are the "last man picked" collectors; the 'PS' collectors like to work with each other; and ParNew and Concurrent like to work together. 

 譯文:以上即使存在的所有的垃圾收集器,但是他們分別在兩塊不同的堆區域上執行,針對一個特定的JVM,我們最終需要的記憶體設定是新生代和老年代的收集器組合。

因此,我將會列舉所有可能的收集器組合。這並不會造成組合數量激增,因為並不是所有的垃圾收集器都能愉快地兩兩組合。G1是最不善社交的收集器,它和任何一個別的收集器都不合群;單執行緒收集器是那個最後的備胎收集器;多執行緒"PS"收集器喜歡互相一起玩;ParNew喜歡和CMS一起工作。

 

The full list of possible GC algorithm combinations that can work are:

Command Options* Resulting Collector Combination
-XX:+UseSerialGC young Copy and old MarkSweepCompact
-XX:+UseG1GC young G1 Young and old G1 Mixed
-XX:+UseParallelGC -XX:+UseParallelOldGC -XX:+UseAdaptiveSizePolicy young PS Scavenge old PS MarkSweep with adaptive sizing
-XX:+UseParallelGC -XX:+UseParallelOldGC -XX:-UseAdaptiveSizePolicy young PS Scavenge old PS MarkSweep, no adaptive sizing
-XX:+UseParNewGC (deprecated in Java 8 and removed in Java 9 - for ParNew see the line below which is NOT deprecated) young ParNew old MarkSweepCompact
-XX:+UseConcMarkSweepGC -XX:+UseParNewGC young ParNew old ConcurrentMarkSweep**
-XX:+UseConcMarkSweepGC -XX:-UseParNewGC (deprecated in Java 8 and removed in Java 9) young Copy old ConcurrentMarkSweep**
*All the combinations listed here will fail to let the JVM start if you add another GC algorithm not listed, with the exception of -XX:+UseParNewGC which is only combinable with -XX:+UseConcMarkSweepGC
**there are many many options for use with -XX:+UseConcMarkSweepGC which change the algorithm, e.g.
  • -XX:+/-CMSIncrementalMode (deprecated in Java 8 and removed in Java 9) - uses or disables an incremental concurrent GC algorithm
  • -XX:+/-CMSConcurrentMTEnabled - uses or disables parallel (multiple threads) concurrent GC algorithm
  • -XX:+/-UseCMSCompactAtFullCollection - uses or disables a compaction when a full GC occurs

 

 

三、收集器組合--通過程式進行引數測試

1.測試程式

import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.util.List;

public class Test {
    public static void main(String args[]) {
        List<GarbageCollectorMXBean> l = ManagementFactory.getGarbageCollectorMXBeans();
        assert (l != null && l.size() ==2);
        assert(l.size() == 2);

        for (int i = 0; i < l.size(); i++) {
            GarbageCollectorMXBean garbageCollectorMXBean = l.get(i);
            if (i == 0){
                System.out.println("young generation:" + garbageCollectorMXBean.getName());
            }else if (i == 1){
                System.out.println("old generation:" + garbageCollectorMXBean.getName());
            }
        }
    }
}

2.測試過程

2.0 《深入java虛擬機器》中展示的虛擬機器組合

以上共有7種組合。我們在下面一一測試。

本機環境:(jdk 1.8,Server模式)

E:\javabase\src>java -XX:+PrintCommandLineFlags -version
-XX:InitialHeapSize=126839040 -XX:MaxHeapSize=2029424640 -XX:+PrintCommandLineFl
ags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesInd
ividualAllocation -XX:+UseParallelGC
java version "1.8.0_11"
Java(TM) SE Runtime Environment (build 1.8.0_11-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.11-b03, mixed mode)

 

 

2.1 預設無引數

E:\javabase\src>java Test
young generation:PS Scavenge
old generation:PS MarkSweep

根據前面的介紹,PS Scavenge對應Parallel Scavenge,PS MarkSweep對應Parallel Old,

即對應上圖中的連線組合6.

 

2.2 -XX:+UseSerialGC

E:\javabase\src>java -XX:+UseSerialGC Test
young generation:Copy
old generation:MarkSweepCompact

對應上圖中的連線組合2.

 

 

2.3 +UseG1GC

E:\javabase\src>java -XX:+UseG1GC Test
young generation:G1 Young Generation
old generation:G1 Old Generation

對應上圖中的連線組合7.

 

 

2.4 -XX:+UseParallelGC -XX:+UseParallelOldGC -XX:+UseAdaptiveSizePolicy

E:\javabase\src>java -XX:+UseParallelGC -XX:+UseParallelOldGC -XX:+UseAdaptiveSizePolicy Test

young generation:PS Scavenge
old generation:PS MarkSweep

對應上圖中的連線組合5.

 

2.5 -XX:+UseParallelGC -XX:+UseParallelOldGC -XX:-UseAdaptiveSizePolicy

E:\javabase\src>java -XX:+UseParallelGC -XX:+UseParallelOldGC -XX:-UseAdaptiveSizePolicy Test
young generation:PS Scavenge
old generation:PS MarkSweep

對應上圖中的連線組合5.

 

2.6 -XX:+UseParNewGC

E:\javabase\src>java -XX:+UseParNewGC Test
Java HotSpot(TM) 64-Bit Server VM warning: Using the ParNew young collector with the Serial old collector is deprecated and will likely be removed in a future release
young generation:ParNew
old generation:MarkSweepCompact

對應上圖中的連線組合4. 該組合已過期,在未來版本將會移除。

 

 

2.7 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC

E:\javabase\src>java -XX:+UseConcMarkSweepGC -XX:+UseParNewGC Test
young generation:ParNew
old generation:ConcurrentMarkSweep

對應上圖中的連線組合3

 

2.8 -XX:+UseConcMarkSweepGC -XX:-UseParNewGC

E:\javabase\src>java -XX:+UseConcMarkSweepGC -XX:-UseParNewGC Test
Java HotSpot(TM) 64-Bit Server VM warning: Using the DefNew young collector with the CMS collector is deprecated and will likely be removed in a future release
young generation:Copy
old generation:ConcurrentMarkSweep

對應上圖中的連線組合1.  該組合已過期,在未來版本將會移除。

 

四、收集器組合--通過jconsole進行引數測試

1.-XX:+UseSerialGC

C:\Users\Administrator\Desktop>java -XX:+UseSerialGC -jar javadoc-jar-vi
ewer-1.0.jar

 

 

2.-XX:+UseG1GC

 

 

3.-XX:+UseParallelGC -XX:+UseParallelOldGC -XX:+UseAdaptiveSizePolicy

 

4.-XX:+UseParallelGC -XX:+UseParallelOldGC -XX:-UseAdaptiveSizePolicy

 

5.-XX:+UseParNewGC 

 

該選項會有過期的提示:

C:\Users\Administrator\Desktop>java -XX:+UseParNewGC -jar javadoc-jar-viewer-1.
0.jar
Java HotSpot(TM) 64-Bit Server VM warning: Using the ParNew young collector with
the Serial old collector is deprecated and will likely be removed in a future r
elease

 

6.-XX:+UseConcMarkSweepGC -XX:+UseParNewGC 

 

7.-XX:+UseConcMarkSweepGC -XX:-UseParNewGC 

該組合選項會有警告提示:

C:\Users\Administrator\Desktop>java -XX:+UseConcMarkSweepGC -XX:-UseParNewGC -ja
r javadoc-jar-viewer-1.0.jar
Java HotSpot(TM) 64-Bit Server VM warning: Using the DefNew young collector with
the CMS collector is deprecated and will likely be removed in a future release

 

 

 五、其他選項(效果同上)

Command Options Used On Their Own Equivalent To Entry In Table Above
-XX:+UseParallelGC -XX:+UseParallelGC -XX:+UseParallelOldGC
-XX:+UseParallelOldGC -XX:+UseParallelGC -XX:+UseParallelOldGC
-Xincgc (deprecated in Java 8 and removed in Java 9) -XX:+UseParNewGC -XX:+UseConcMarkSweepGC
-XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+UseConcMarkSweepGC
no option on most Windows -XX:+UseG1GC from Java 9, or before that -XX:+UseSerialGC (see also this page)
no option on most Unix -XX:+UseG1GC from Java 9, or before that -XX:+UseParallelGC -XX:+UseParallelOldGC -XX:+UseAdaptiveSizePolicy (see also this page)
-XX:+AggressiveHeap -XX:+UseParallelGC -XX:+UseParallelOldGC -XX:+UseAdaptiveSizePolicy with a bunch of other options related to sizing memory and threads and how they interact with the OS

 

1.-XX:+UseParallelGC

 

 

 

 

2.-XX:+UseParallelOldGC

 

3.-Xincgc 

C:\Users\Administrator\Desktop>java -Xincgc -jar javadoc-jar-viewer-1.0.jar
Java HotSpot(TM) 64-Bit Server VM warning: Using incremental CMS is deprecated a
nd will likely be removed in a future release

 

4.-XX:+UseConcMarkSweepGC

 

 5.windows上預設無選項時

 

 

 6.-XX:+AggressiveHeap

 

六、參考資料

滑鼠點選設定jvm引數:http://jvmmemory.com/