相信不少人都看過下面這張圖,(來自《深刻理解Java虛擬機:JVM高級特性與最佳實踐》)html
在學完幾種垃圾收集器類型及組合後,打算看看實際中程序用到的垃圾收集器。java
可是在jconsole中看到的,以下:linux
兩邊的名稱並不徹底匹配,給我形成了不少困惑之處。算法
實際上,jconsole裏面用到的,我想應該是JVM內部使用到的名字。windows
本文主要講解新生代、老年代可用的垃圾收集器,如何查看運行中程序使用的垃圾收集器,可用的垃圾收集器組合及對應參數配置等。多線程
資料來源於:oracle
一、《深刻理解Java虛擬機:JVM高級特性與最佳實踐》app
二、http://www.fasterj.com/articles/oraclecollectors1.shtmljvm
-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.ide
譯文:Serial垃圾收集器,使用單線程完成下列工做:
從Eden區和From Survivor區拷貝存活對象到To Survivor區域、當存活對象在Survivor區超過年齡閾值時,拷貝到老年代。
這裏的名稱爲Copy,實際上就是上圖的Serial收集器。
-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]。
-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收集器的多線程版本, 除了使用多條線程進行垃圾收集。
-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.
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收集器的老年代版本, 它一樣是一個單線程收集器, 使用「標記-整理」 算法。
the parallel scavenge mark-sweep collector, parallelised version (i.e. uses multiple threads) of the MarkSweepCompact.
Parallel Old是Parallel Scavenge收集器的老年代版本, 使用多線程和「標記-整理」 算法。
一樣,也是上面MarkSweepCompact 的多線程版本。
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 )收集器來從新進行老年代的垃圾收集, 這樣停頓時間就很長了。
the garbage first collector, uses the 'Garbage First' algorithm which splits up the heap into lots of smaller spaces.
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算法(該算法會徹底阻止應用程序的運行)
以上只是簡單介紹,詳細能夠參考書籍或者如下連接:
若是程序已經處於運行狀態,可以使用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.
|
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()); } } } }
以上共有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)
E:\javabase\src>java Test
young generation:PS Scavenge
old generation:PS MarkSweep
根據前面的介紹,PS Scavenge對應Parallel Scavenge,PS MarkSweep對應Parallel Old,
即對應上圖中的連線組合6.
E:\javabase\src>java -XX:+UseSerialGC Test
young generation:Copy
old generation:MarkSweepCompact
對應上圖中的連線組合2.
E:\javabase\src>java -XX:+UseG1GC Test
young generation:G1 Young Generation
old generation:G1 Old Generation
對應上圖中的連線組合7.
E:\javabase\src>java -XX:+UseParallelGC -XX:+UseParallelOldGC -XX:+UseAdaptiveSizePolicy Test
young generation:PS Scavenge
old generation:PS MarkSweep
對應上圖中的連線組合5.
E:\javabase\src>java -XX:+UseParallelGC -XX:+UseParallelOldGC -XX:-UseAdaptiveSizePolicy Test
young generation:PS Scavenge
old generation:PS MarkSweep
對應上圖中的連線組合5.
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. 該組合已過時,在將來版本將會移除。
E:\javabase\src>java -XX:+UseConcMarkSweepGC -XX:+UseParNewGC Test
young generation:ParNew
old generation:ConcurrentMarkSweep
對應上圖中的連線組合3
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. 該組合已過時,在將來版本將會移除。
C:\Users\Administrator\Desktop>java -XX:+UseSerialGC -jar javadoc-jar-vi ewer-1.0.jar
該選項會有過時的提示:
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
該組合選項會有警告提示:
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
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
鼠標點選設置jvm參數:http://jvmmemory.com/
jvm參數查詢 : http://xxfox.perfma.com/jvm/query