素小暖讲JVM:HotSpot VM GC 的种类

本系列是用来记录《深刻理解Java虚拟机》这本书的读书笔记。方便本身查看,也方便你们查阅。java

欲速则不达,欲达则欲速!服务器

1、collector种类多线程

GC在 HotSpot VM 5.0里有四种:并发

incremental (sometimes called train) low pause collector已被废弃,不在介绍app

类别 serial collector parallel collector
throughput collector )
concurrent collector
(concurrent low pause collector)
介绍

单线程收集器性能

使用单线程去完成全部的GC工做,没有线程间的通讯,这种方式会相对高效spa

并行收集器线程

使用多线程的方式,利用CUP来提升GC的效率,主要以到达必定的吞吐量为目标code

并发收集器orm

使用多线程的方式,利用多CPU来提升GC的效率,并发完成大部分工做,使得GC pause短

试用场景 单处理器机器且没有pause time的要求

适用于科学技术和后台处理有中大规模数据集的应用

且运行在多处理器上,关注吞吐量(throughput)

适合中规模/大规模数据集大小的应用,应用服务器,电信领域。关注response time,而不是throughput
使用 Client模式下默认
可以使用
可用-XX:+UseSerialGC强制使用
优势:对server应用没什么优势
缺点:慢,不能充分发挥硬件资源

Server模式下默认

--YGC:PS FGC:Parallel MSC

可用-XX:+UseParallelGC

或-XX:+UseParallelOldGC强制指定

--ParallelGC表明FGC为Parallel MSC

--ParallelOldGC表明FGC为Parallel Compacting

优势:高效

缺点:当heap变大后,形成的暂停时间会变得比较长

可用-XX:+UseConcMarkSweepGC强制指定

优势:
对old进行回收时,对应用形成的暂停时间很是短,适合对延迟要求比较高的应用

缺点:
1.内存碎片和浮动垃圾
2.old去的内存分配效率低
3.回收的整个耗时比较长
4.和应用争抢CPU

内存回收触发

YGC
eden空间不足
FGC
old空间不足
perm空间不足
显示调用System.gc() ,

包括RMI等的定时触发

YGC
eden空间不足
FGC
old空间不足
perm空间不足
显示调用System.gc() ,包括RMI等的定时触发

YGC
eden空间不足
CMS GC
1.old Gen的使用率大的必定的比率 默认为92%
2.配置了CMSClassUnloadingEnabled,且Perm Gen的使用达到必定的比率 默认为92%
3.Hotspot本身根据估计决定是否要触法
4.在配置了ExplictGCInvokesConcurrent的状况下显示

调用了System.gc.
Full GC(Serial MSC)
promotion failed 或 concurrent Mode Failure时;

内存回收触发

时发生了什么

YGC
清空eden+from中全部no ref的对象占用的内存
将eden+from中的全部存活的对象copy到to中
在这个过程当中一些对象将晋升到old中:
--to放不下的
--存活次数超过tenuring threshold的
从新计算Tenuring Threshold;
单线程作以上动做
全程暂停应用
FGC
若是配置了CollectGen0First,则先触发YGC
清空heap中no ref的对象,permgen中已经被卸载的classloader

中加载的class的信息
单线程作以上动做
全程暂停应用

YGC
同serial动做基本相同,不一样点:
1.多线程处理
2.YGC的最后不只从新计算Tenuring Threshold,还会从新调整Eden和From的大小
FGC
1.如配置了ScavengeBeforeFullGC(默认),则先触发YGC(??)
2.MSC:清空heap中的no ref对象,permgen中已经被卸载的classloader中加载的

class信息,并进行压缩
3.Compacting:清空heap中部分no ref的对象,permgen中已经被卸载的classloader中加载的

class信息,并进行部分压缩
多线程作以上动做.

YGC
同serial动做基本相同,不一样点:
1.多线程处理
CMSGC:
1.old gen到达比率时只清除old gen中no ref的对象所占用的空间
2.perm gen到达比率时只清除已被清除的classloader

加载的class信息
FGC
同serial

细节参数 可用-XX:+UseSerialGC强制使用
-XX:SurvivorRatio=x,控制eden/s0/s1的大小
-XX:MaxTenuringThreshold,用于控制对象在新生代存活的最大次数
-XX:PretenureSizeThreshold=x,控制超过多大的字节的对象就在old分配.
-XX:SurvivorRatio=x,控制eden/s0/s1的大小
-XX:MaxTenuringThreshold,用于控制对象在新生代存活的最大次数

-XX:UseAdaptiveSizePolicy 去掉YGC后动态调整eden from已经tenuringthreshold的动做

-XX:ParallelGCThreads 设置并行的线程数

XX:CMSInitiatingOccupancyFraction 设置old gen使用到达多少比率时触发
-XX:CMSInitiatingPermOccupancyFraction,设置Perm Gen使用到达多少比率时触发
-XX:+UseCMSInitiatingOccupancyOnly禁止hostspot自行触发CMS GC

注:

  • throughput collector与concurrent low pause collector的区别是throughput collector只在young area使用使用多线程,而concurrent low pause collector则在tenured generation也使用多线程。
  • 根据官方文档,他们俩个须要在多CPU的状况下,才能发挥做用。在一个CPU的状况下,会不如默认的serial collector,由于线程管理须要耗费CPU资源。而在两个CPU的状况下,也提升不大。只是在更多CPU的状况下,才会有所提升。固然 concurrent low pause collector有一种模式能够在CPU较少的机器上,提供尽量少的停顿的模式,见CMS GC Incremental mode
  • 当要使用throughput collector时,在java opt里加上-XX:+UseParallelGC,启动throughput collector收集。也可加上-XX:ParallelGCThreads=<desired number>来改变线程数。还有两个参数 -XX:MaxGCPauseMillis=<nnn>和 -XX:GCTimeRatio=<nnn>,MaxGCPauseMillis=<nnn>用来控制最大暂停时间,而-XX: GCTimeRatio能够提升GC说占CPU的比,以最大话的减少heap。

2、CMS GC Incremental mode

 当要使用 concurrent low pause collector时,在java的opt里加上 -XX:+UseConcMarkSweepGC。concurrent low pause collector还有一种为CPU少的机器准备的模式,叫Incremental mode。这种模式使用一个CPU来在程序运行的过程当中GC,只用不多的时间暂停程序,检查对象存活。

在Incremental mode里,每一个收集过程当中,会暂停两次,第二次略长。第一次用来,简单从root查询存活对象。第二次用来,详细检查存活对象。整个过程以下:

* stop all application threads; do the initial mark; resume all application threads(第一次暂停,初始话标记)
* do the concurrent mark (uses one procesor for the concurrent work)(运行是标记)
* do the concurrent pre-clean (uses one processor for the concurrent work)(准备清理)
* stop all application threads; do the remark; resume all application threads(第二次暂停,标记,检查)
* do the concurrent sweep (uses one processor for the concurrent work)(运行过程当中清理)
* do the concurrent reset (uses one processor for the concurrent work)(复原)

当要使用Incremental mode时,须要使用如下几个变量:

-XX:+CMSIncrementalMode default: disabled 启动i-CMS模式(must with -XX:+UseConcMarkSweepGC)
-XX:+CMSIncrementalPacing default: disabled 提供自动校订功能
-XX:CMSIncrementalDutyCycle=<N> default: 50 启动CMS的上线
-XX:CMSIncrementalDutyCycleMin=<N> default: 10 启动CMS的下线
-XX:CMSIncrementalSafetyFactor=<N> default: 10 用来计算循环次数
-XX:CMSIncrementalOffset=<N> default: 0 最小循环次数(This is the percentage (0-100) by which the incremental mode duty cycle is shifted to the right within the period between minor collections.)
-XX:CMSExpAvgFactor=<N> default: 25 提供一个指导收集数

SUN推荐的使用参数是:

-XX:+UseConcMarkSweepGC \
-XX:+CMSIncrementalMode \
-XX:+CMSIncrementalPacing \
-XX:CMSIncrementalDutyCycleMin=0 \
-XX:CMSIncrementalDutyCycle=10 \
-XX:+PrintGC Details \
-XX:+PrintGCTimeStamps \
-XX:-TraceClassUnloading
注:若是使用throughput collector和concurrent low pause collector,这两种垃圾收集器,须要适当的挺高内存大小,觉得多线程作准备。

3、如何选择collector

app运行在单处理器机器上且没有pause time的要求,让vm选择单线程收集器serial collector。

重点考虑peak application performance(高性能),没有pause time太严格要求,选择并行收集器parallel collector。

重点考虑response time,pause time要小,选择并发收集器concurrent collector。

 

鸣谢:特别感谢做者周志明提供的技术支持!

相关文章
相关标签/搜索