JVM垃圾收集器
2020-09-08 20:51:03 0 举报
分析 JVM7 大垃圾收集器
作者其他创作
大纲/内容
Parallel Old是Parallel Scavenge收集器的老年代版本,支持多线程并发收集,基于标记-整理算法实现。这个收集器是直到JDK 6时才开始提供的,在此之前,新生代的Parallel Scavenge收集器一直处于相当尴尬的状态,原因是如果新生代选择了Parallel Scavenge收集器,老年代除了Serial Old(PS MarkSweep)收集器以外别无选择,其他表现良好的老年代收集器,如CMS无法与它配合工作。由于老年代Serial Old收集器在服务端应用性能上的“拖累”,使用Parallel Scavenge收集器也未必能在整体上获得吞吐量最大化的效果。由于单线程的老年代收集中无法充分利用服务器多处理器的并行处理能力,在老年代内存空间很大而且硬件规格比较高级的运行环境中,这种组合的总吞吐量甚至不一定比ParNew加CMS的组合来得优秀。直到Parallel Old收集器出现后,“吞吐量优先”收集器终于有了比较名副其实的搭配组合,在注重吞吐量或者处理器资源较为稀缺的场合,都可以优先考虑Parallel Scavenge加Parallel Old收集器这个组合。
Serial Old收集器
Parallel Scavenge收集器
新生代
1、特点 Serial收集器的读线程版本,运行在服务端模式下的HotSpot虚拟机,可与Serial Old收集器或CMS收集器组合使用,由于G1的出现已近不推荐这种组合了。 ParNew收集器在单核心处理器的环境中绝对不会有比Serial收集器更好的效果,甚至由于存在线程交互的开销,该收集器在通过超线程(Hyper-Threading)技术实现的伪双核处理器环境中都不能百分之百保证超越Serial收集器。当然,随着可以被使用的处理器核心数量的增加,ParNew对于垃圾收集时系统资源的高效利用还是很有好处的。
CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。(并发低停顿收集器)1.初始标记(需要“Stop The World”):仅标记一下GC Roots能直接关联到的对象,速度很快2.并发标记:从GC Roots的直接关联对象开始遍历整个对象图的过程,这个过程耗时较长但是不需要停顿用户线程,可以与垃圾收集线程一起并发运行。(这个过程用户线程可能产生新的垃圾)3.重新标记(需要“Stop The World”):修正并发标记期间,因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间通常会比初始标记阶段稍长一些,但也远比并发标记阶段的时间短4.并发清除:清理删除掉标记阶段判断的已经死亡的对象,由于不需要移动存活对象,所以这个阶段也是可以与用户线程同时并发的。(此阶段用户仍然可以产生新的垃圾)缺点:1.在并发阶段,它虽然不会导致用户线程停顿,但却会因为占用了一部分线程(或者说处理器的计算能力)而导致应用程序变慢,降低总吞吐量。(CMS默认启动的回收线程数是(处理器核心数量+3)/4,如果处理器核心数在四个或以上,并发回收时垃圾收集线程只占用不超过25%的处理器运算资源,并且会随着处理器核心数量的增加而下降。但是当处理器核心数量不足四个时,CMS对用户程序的影响就可能变得很大。)【虚拟机提供了一种称为“增量式并发收集器”(Incremental Concurrent Mark Sweep/i-CMS)的CMS收集器变种,所做的事情和以前单核处理器年代PC机操作系统靠抢占式多任务来模拟多核并行多任务的思想一样,是在并发标记、清理的时候让收集器线程、用户线程交替运行,尽量减少垃圾收集线程的独占资源的时间,这样整个垃圾收集的过程会更长,但对用户程序的影响就会显得较少一些,直观感受是速度变慢的时间更多了,但速度下降幅度就没有那么明显。(降低系统变慢速度拉长变慢时间,JDK9之后被废弃)】2.浮动垃圾:在CMS的并发标记和并发清理阶段,用户线程是还在继续运行的,程序在运行自然就还会伴随有新的垃圾对象不断产生,但这一部分垃圾对象是出现在标记过程结束以后,CMS无法在当次收集中处理掉它们,只好留待下一次垃圾收集时再清理掉。这一部分垃圾就称为“浮动垃圾”。由于在垃圾收集阶段用户线程还需要持续运行,那就还需要预留足够内存空间提供给用户线程使用,因此CMS收集器不能像其他收集器那样等待到老年代几乎完全被填满了再进行收集,必须预留一部分空间供并发收集时的程序运作使用。该预留空间调的太低会导致GC频繁,调得太高可能会导致用户需要得空间无法得到满足,而导致冻结冻结当前用户线程,进行备选方案Serial Old收集器进行一次FullGC,此过程会十分耗时。所以对于老年代增长速度不快的我们可以适当调高,并且可以获得好的响应性能。3.由于CMS采用了标记-清除算法,很显然会产生很多内存碎片,过多得内存碎片可能会导致将需要较到得连续空间是无法得到满足,此时我们不得不进行FullGC并且清理内存碎片,但此过程是不能有用户线程的,且会停顿比较长的时间。(虚拟机设计者们还提供了另外一个参数-XX:CMSFullGCsBefore-Compaction(此参数从JDK 9开始废弃),这个参数的作用是要求CMS收集器在执行过若干次(数量由参数值决定)不整理空间的Full GC之后,下一次进入FullGC前会先进行碎片整理(默认值为0,表示每次进入Full GC时都进行碎片整理)。)
1、特点 单线程收集:进行垃圾收集时,必须暂停所有工作线程,直到完 成。即会\"Stop The World\";(用户体验较差) 优点:简单高效,相比其他收集器额外内存消耗最小的,没有线程切换的开销 在用户桌面的应用场景以及近年来流行的部分微服务应用中,分配给虚拟机管理的内存一般来说并不会特别大,收集几十兆甚至一两百兆的新生代(仅仅是指新生代使用的内存,桌面应用甚少超过这个容量),垃圾收集的停顿时间完全可以控制在十几、几十毫秒,最多一百多毫秒以内,只要不是频繁发生收集,这点停顿时间对许多用户来说是完全可以接受的。所以,Serial收集器对于运行在客户端模式下的虚拟机来说是一个很好的选择。(小内存收集方面比较适合)
Parallel Old收集器
CMS收集器
ParNew收集器
Serial Old是Serial收集器的老年代版本,它同样是一个单线程收集器,使用标记-整理算法。它也可能有两种用途:一种是在JDK 5以及之前的版本中与Parallel Scavenge收集器搭配使用,另外一种就是作为CMS收集器发生失败时的后备预案,在并发收集发生Concurrent Mode Failure时使用。
老年代
Garbage First收集器
Serial收集器
Parallel Scavenge收集器与ParNew收集器非常类似,用于新生代的多线程收集器,采用了标记复制算法。Parallel Scavenge收集器的目标则达到一个可控制的吞吐量(Throughput)。所谓吞吐量就是处理器用于运行用户代码的时间与处理器总消耗时间的比值自适应调节策略也是Parallel Scavenge收集器区别于ParNew收集器的一个重要特性。如果我们对堆内存分配不太确定,我们可以设置该收集器,然后设置一个优化目标,该收集器会自动对堆的大小比列进行调整。只需要把基本的内存数据设置好(如-Xmx设置最大堆),然后使用-XX:MaxGCPauseMillis参数(更关注最大停顿时间)或-XX:GCTimeRatio(更关注吞吐量)参数给虚拟机设立一个优化目标,那具体细节参数的调节工作就由虚拟机完成了
0 条评论
回复 删除
下一页