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算法(该算法会完全阻止应用程序的运行)
以上只是简单介绍,详细可以参考书籍或者以下链接:
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.
|
三、收集器组合--通过程序进行参数测试
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/
jvm参数查询 : http://xxfox.perfma.com/jvm/query