HotSpot虚拟机提供了7种作用于不同分代的收集器,如果两个收集器之间存在连线,就说明它们
可以搭配使 用。虚拟机所处的区域,则表示它是属于新生代收集器还是老年代收集器。
CMS和G1这两款收集器相对比较复杂,也是重点讨论的收集器。
1. Serial收集器(新生代收集器,串行GC)
特性:
单线程
串行:指垃圾回收线程与用户线程是串行的,会造成用户线程暂停,也就是Stop The
World(STW)
应用场景:
Client模式下的默认新生代收集器。
优势:
单个CPU的环境来说,Serial收集器由于没有线程交互的开销,专心做垃圾收集自然可以获得最高
的单线程收集效率。
在用户的桌面应用场景中,分配给虚拟机管理的内存一般来说不会很大,收集几十兆甚至一两百兆
的新生代(仅仅是新生代使用的内存,桌面应用基本上不会再大了),停顿时间完全可以控制在几
十毫秒最多一百多毫秒以内,只要不是频繁发生,这点停顿是可以接受的。所以,Serial收集器对
于运行在Client模式下的虚拟机来说是一个很好的选择。
2. ParNew收集器(新生代收集器,并行GC)
特性:
Serial收集器的多线程版本,除了使用多条线程进行垃圾收集之外,其余行为包括Serial收集器可
用的所有控制参数、收集算法、Stop The World、对象分配规则、回收策略等都与Serial收集器完
全一样,在实现上,这两种收集器也共用了相当多的代码。
应用场景:
运行在Server模式下的虚拟机中首选的新生代收集器,其中有一个与性能无关但很重要的原因是,
除了Serial收集器外,目前只有它能与CMS收集器配合工作。
优势:
相比单CPU环境,随着可以使用的CPU的数量的增加,它对于GC时系统资源的有效利用还是很有
好处的。
3 Parallel Scavenge收集器(新生代收集器,并行GC)
特性:
多线程
复制算法
可控制的吞吐量(Throughput)。Parallel Scavenge收集器提供了两个参数用于精确控制吞吐
量,分别是控制最大垃圾收集停顿时间的-XX:MaxGCPauseMillis参数以及直接设置吞吐量大小
的-XX:GCTimeRatio参数。
自适应的调节策略:Parallel Scavenge收集器有一个参数- XX:+UseAdaptiveSizePolicy 。当这个
参数打开之后,就不需要手工指定新生代的大小、Eden与Survivor区的比例、晋升老年代对象年
龄等细节参数了,虚拟机会根据当前系统的运行情况收集性能监控信息,动态调整这些参数以提供
最合适的停顿时间或者最大的吞吐量,这种调节方式称为GC自适应的调节策略(GC
Ergonomics)。
应用场景:
“吞吐量优先”收集器,适用吞吐量需求高的任务型程序。
4 Serial Old收集器(老年代收集器,串行GC)
特性:
Serial Old是Serial收集器的老年代版本,它同样是一个单线程收集器,使用“标记-整理”算法。
应用场景:
给Client模式下的虚拟机使用。
在Server模式下,那么它主要还有两大用途:
5. Parallel Old收集器(老年代收集器,并行GC)
特性:
Parallel Scavenge收集器的老年代版本,使用多线程和“标记-整理”算法。
应用场景:
在注重吞吐量以及CPU资源敏感的场合,都可以优先考虑Parallel Scavenge加Parallel Old收集
器。
6 CMS收集器(老年代收集器,并发GC)
CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。
特性:
并发收集、低停顿
基于“标记—清除”算法实现的。
整个过程分为4个步骤:
由于整个过程中耗时最长的并发标记和并发清除过程收集器线程都可以与用户线程一起工作,所
以,从总体上来说,CMS收集器的内存回收过程是与用户线程一起并发执行的。
应用场景:
目前很大一部分的Java应用集中在互联网站或者B/S系统的服务端上,这类应用尤其重视服务的响
应速度,希望系统停顿时间最短,以给用户带来较好的体验。CMS收集器就非常符合这类应用的
需求。
缺陷:
1).CMS会抢占CPU资源。并发阶段虽然不会导致用户线程暂停,但却需要CPU分出精力去执行多条
垃圾收集线程,从而使得用户线程的执行速度下降。
2).CMS无法处理浮动垃圾(Floating Garbage),可能会出现“Concurrent Mode Failure”而导致另一
次Full GC。并发清理的过程中,由于用户线程还在执行,因此就会继续产生对象和垃圾,这些新
的垃圾没有被标记,CMS只能在下一次收集中处理它们。这也导致了CMS不能在老年代几乎完全
被填满了再去进行收集,必须预留一部分空间提供给并发收集时程序运作使用。在JDK1.5默认设
置下,老年代使用了68%(JDK1.6是92%)的空间后CMS的垃圾收集就会被激活,其实这是一个比较
保守的设置,只要应用中老年代增长不是很快,可以适当地调高参数-
XX:CMSInitialingOccupancyFraction来提高触发百分比,降低回收的频率来获得更好的性能。如
果CMS在收集期间,内存无法满足程序的需要,就会出现“Concurrent Mode Failure”,这时JVM
将启动Plan B,也就是临时调用单线程的Serial Old收集器来重新进行老年代的垃圾收集,这样的
话,CMS原本降低停顿时间的目的不仅没完成,和直接使用Serial Old收集器相比,还增加了前面
几个阶段的停顿时间。
3).CMS的“标记-清除”算法,会导致大量空间碎片的产生。碎片的积累会给分配大对象带来麻烦,往
往会出现明明老年代还有很多空间剩余,但是却无法找到连续的空间分配对象的情况,这时候就不
得不触发一次Full GC。为了解决这个问题。CMS提供了一个
XX:+UseCMSCompactAtFullCollection的开关参数(默认是开启的),用于在CMS收集器进行Full
GC时对内存碎片进行合并整理,整理的过程是需要暂停用户线程的,这样碎片虽然没有了,但停
顿时间又变长了。CMS的设计初衷可是降低停顿,于是又提供了一个参数-
XX:CMSFullGCsBeforeCompaction,用于设置执行多少次不压缩碎片的Full GC后,跟着来一次带
压缩的Full GC(默认值为0,即每次都会)。
7.G1(Garbage-First)收集器
特点:
1.并行与并发:G1能充分利用多CPU、多核环境下的硬件优势,使用多个CPU(CPU或者CPU核心) 来缩短Stop-The-World停顿的时间,部分其他收集器原本需要停顿Java线程执行的GC动作,G1收集器仍 然可以通过并发的方式让Java程序继续执行。
2.分代收集:与其他收集器一样,分代概念在G1中依然得以保留。虽然G1可以不需要其他收集器配 合就能独立管理整个GC堆,但它能够采用不同的方式去处理新创建的对象和已经存活了一段时间、熬过多次GC的旧对象以获取更好的收集效果。
3.空间整合:与CMS的“标记—清理”算法不同,G1从整体来看是基于“标记—整理”算法实现的收集 器,从局部(两个Region之间)上来看是基于“复制”算法实现的,但无论如何,这两种算法都意味着G1 运作期间不会产生内存空间碎片,收集后能提供规整的可用内存。这种特性有利于程序长时间运行,分配大对象时不会因为无法找到连续内存空间而提前触发下一次GC。
4.可预测的停顿:这是G1相对于CMS的另一大优势,降低停顿时间是G1和CMS共同的关注点,但G1 除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为M毫秒的时间 片段内,消耗在垃圾收集上的时间不得超过N毫秒,这几乎已经是实时Java(RTSJ)的垃圾收集器的特征了
G1的运行步骤:
1、初始标记:整个过程STW,标记了从GC Roots 的可达对象
2、并发标记 :整个过程用户线程的垃圾回收线程共同执行,标记出GC Roots可达对象的关联对象,收集整个Region的存活对象。
3、最终标记:整个过程STW,标记出并发标记遗漏的,以及引用关系发生变化的存活对象。
4、筛选回收:垃圾清理过程,如果整个Region没有存活对象,将Region加入到存活列表当中。
JVM参数
jvm参数,即为配置jvm虚拟机的参数,都在调用java命令开启虚拟机的时候指定。具体见官方java-doc
说明文档的首页,如上图图中java链接,点击进去就是jvm参数及说明,monitoring就是监控命令及说明。 比较重要的参数如下: