Java GC(1)—— Java 经典垃圾收集器

一、Serial收集器

1. 简介

Serial收集器是最基础、历史最悠久的收集器,在jdk1.3之前,也是新生代垃圾收集器的唯一选择。它是单线程工作的,且在垃圾收集期间需要暂停所有的用户线程,也称为“Stop The World”,简写为STW,这个动作由虚拟机自行发起,在用户不可知、不可控的情况下,每工作一段时间就会暂停收集垃圾带来的就是并不友好的用户体验。

2.工作机制

运行流程示意图如下

image

3.意义

HotSpot虚拟机团队一直在为降低STW导致的停顿而努力,不断推陈出新,研发了许多新的收集器,比如Parallel、CMS、G1,越来越优秀、越来越复杂,虽然仍然不能完全消除停顿,但已经使得停顿时间得到了极大的缩减。
尽管已经有了许多新兴的垃圾收集器,但Serial收集器并非一个老而无用的鸡肋,起码直至Jdk1.8,它依然是客户端模式下默认的新生代默认的垃圾收集器,其最大的优点就是:简单高效
在内存有限的环境里,它是消耗内存最少的;由于它是单线程的,所以不会有线程切换交互的开销,因而它的单线程收集效率也是最高的。 如果新生代空间不大,比如几十兆或者一两百兆,那么它的收集时间就只需要十几乃至几十毫秒,对用户的影响有限。

二、ParNew收集器

1.简介

ParNew收集器实际上是Serial的多线程并行版本,也能使用Serial收集器的控制参数,其它行为,例如收集算法、STW、对象分配规则也和Serial一致,甚至在实现上,两者也有许多相同的代码。

2.运行机制

image

和Serial收集器相比,除了支持多线程并行收集,ParNew就没有什么创新之处了,但是在Jdk7之前,它却是服务端运行模式下优先选择的新生代收集器,除了性能之外,这样做的最主要的原因是:它是除Serial以外,唯一能够和Jdk5发布的CMS收集器配合工作的。
在G1出现以前,CMS可以说是跨时代的,真正意义上使得垃圾回收线程和用户线程可以同时工作。CMS的出现巩固了ParNew收集器的地位,但随着G1等更为先进的收集器的迭代,ParNew也逐渐显得过时了,从JDK9开始,ParNew+CMS已经不再是官方推荐的收集器组合了。

3.意义

在多核心的运行环境种,ParNew能够更为高效地利用系统资源,在默认参数下,它会开启核心数相同的垃圾收集线程,在核心数较多的情况下,可以通过使用-XX:ParallelGCThreads参数来限制垃圾收集的线程数。

此处需要注意并行与并发的概念
1.并行:指多个垃圾回收线程协同工作
2.并发:指用户线程和垃圾回收线程同时工作。

三、Parallel Scavenge收集器

1.简介

Parallel Scavenge也是一款新生代收集器,它的特点在于关注点是吞吐量,同样是基于标记——复制算法,从名字也不难看出它是一款能够并行收集的多线程收集器。
所谓吞吐量,指的是处理器用于处理用户代码的时间和总的运行时间的比值:

吞吐量=运行用户代码时间/(运行用户代码时间+运行垃圾回收时间)

停顿时间越短,带给用户的体验就越好;而高吞吐量则可以高效地利用处理器资源,适合那些在后台运算而不需要许多交互的程序。

2.使用

Parallel Scavenge提供了两个参数用于控制吞吐量,分别是:-XX:MaxGCPauseMillis用于控制最大停顿时间,以及-XX:GCTimeRatio用于直接控制吞吐量。

-XX:MaxGCPauseMillis:接受一个大于0的数,单位是毫秒,收集器将会尽力保证内存回收的时间不超过这个设定值。但任何好处都不可能是毫无代价的,越短的响应时间意味着更小的吞吐量和更小的新生代,新生代空间越小则必然导致垃圾回收行为更为频繁。
-XX:GCTimeRatio: 接收一个0到100之间的整数,是运行用户代码时间和垃圾收集时间的比值。举个例子,默认的数值是99,这就意味着垃圾回收的时间占比为1/(1+99),也就是1%。

除了上述的两个参数外,我们还需要关注 -XX:+UseAdaptiveSizePolicy这个参数,它是一个开关,在开启之后就不再需要人工指定新生代大小(-Xmn)、伊甸区和生存区大小的比例(-XX:SurvivorRatio)以及直接晋升老年代的对象的大小(-XX:PretenureSizeThreshold),虚拟机会根据当前系统运行的监控信息,动态调整这些参数,以提供最合适的停顿时间或者最大吞吐量。我们将这种调节方式称之为自适应调节策略,这也是Parallel Scavenge收集器的重要特性之一。

四、Serial Old收集器

1.简介

Serial Old收集器是Serial的老年代版本,它同样是单线程运行的,使用标记——整理算法。这个收集器主要是工作在客户端模式的HotSpot虚拟机使用,如果在服务端模式,那么它可能是在Jdk5以及之前的版本中和Parallel Scavenge收集器搭配,又或者是作为CMS收集器失败时的备选,在发生Concurrent Mode Failure时使用。

2.运行机制

image

五、Parallel Old收集器

1.简介

Parallel Old收集器是Parallel Scavenge的老年代版本,支持多线程并发回收,基于标记——整理算法实现,出现于Jdk6,在此之前,老年代能够与Parallel Scavenge收集器配合使用的只有Serial Old,但Serial Old作为一个单线程收集器,性能表现欠佳,因此,在Parallel Old收集器出现后,“吞吐量优先”的搭配组合才能够得以实现。

2.工作流程

可以参照Parallel Scavenge。

六、CMS收集器

1.介绍

CMS是Concurrent Mark Sweep的缩写,CMS收集器是一款以最短回收停顿时间为目标的收集器,是Jdk6、7、8版本下,基于B/S系统的服务端应用所采用的主要收集器,这类应用通常追求最短的停顿时间,以带给用户良好的使用体验。CMS收集器是基于标记——整理算法实现的。

2.工作机制

CMS收集器的运行过程可以分为四步:

1)初始标记(CMS Initial mark)
2)并发标记(CMS concurrent mark)
3)重新标记(CMS remark)
4)并发清除(CMS concurrent sweep)

其中初始标记和重新标记这两个步骤依然需要STW。
所谓初始标记,只是标记和GC Roots直接关联的对象,速度很快;并发标记阶段会从直接关联对象开始遍历整个对象图,这个过程很长,但可以和用户线程并发运行;重新标记则是为了修正并发标记期间因用户线程继续运行而导致标记产生变动的那部分对象的标记记录;最后是并发清除,这个阶段就是清理标记过的对象,由于不需要移动存活对象,因此可以和用户线程同时运行,故而叫并发清除。

3.运行机制

image

CMS收集器是优秀的,它的优点是:并发、抵停顿,但它依然远称不上完美,CMS收集器起码存在三个缺点:

  • 1.CMS收集器对CPU资源十分敏感
    在并发阶段,它虽然不会导致用户线程停顿,但却占据了一部分线程,这会导致应用程序变慢,降低总吞吐量。CMS收集器默认的线程数是(3+服务器核心数)/4,也就是说如果处理器核心数大于等于4时,占用的CPU资源不会大于25%,CPU核心数越多,占用率还会进一步下降。但是如果核心数不足4个,则CMS收集器对用户程序的影响就会很大,甚至会导致用户程序长期得不到线程资源。
  • 2.CMS收集器无法处理“浮动垃圾”
    并发标记和并发清理阶段,由于用户线程还在继续运行,所以会继续产生垃圾对象,但它们出现于标记阶段之后,因此无法在当次回收中处理掉,只能留待下一次清理,这部分垃圾对象称之为“浮动垃圾”。为此需要预留足够的内存空间给用户线程,而不能像其它收集器那样等到老年代几乎用尽再回收,从Jdk6开始,CMS默认会在老年代使用92%的空间时触发回收,但这就带来了一个风险:CMS运行期间预留的内存无法满足用户线程运行,那么就会触发“并发失败”(Concurrent Mode Failure)。这时虚拟机就会启用备案:暂停所有用户线程,使用Serail Old回收器来清理老年代,这样应用就需要停顿很长时间。所以参数-XX:CMSInitiatingOccupancyFraction设置得太高将会很容易导致大量的并发失败产生,性能反而降低,用户应在生产环境中根据实际应用情况来权衡设置。
  • 3.空间碎片问题
    由于CMS是一款基于标记—清除算法实现实现的收集器,因此必然会产生大量的空间碎片,此时,就算老年代有很多空闲空间,却也没有连续的空间来为大对象分配空间,而不得不触发Full-GC。为了解决这个问题,CMS收集器提供了一个-XX:+UseCMS-CompactAtFullCollection开关参数(Jdk9开始废弃),在整理内存期间无法并发。-XX:CMSFullGCsBefore-Compaction可以在若干次Full-GC之后才整理空间。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值