Java虚拟机3:jvm垃圾收集器

jvm中的垃圾收集器分为两种:

  • Scavenge GC(次收集)
  • Full GC(全收集)

Scavenge GC(次收集)和Full GC(全收集)的区别是什么?

 

新生代GC(Scavenge GC):指发生在新生代的GC,因为新生代的java对象大多都是生命周期较短,所以次收集非常频繁,一般回收速度也比较快,当Eden空间不足以为对象分配内存时,就会触发Scavenge GC。

一般情况下,当新对象生成,并且在Eden申请空间失败时,就会触发Savenge GC,对Eden区域进行GC,清除非存活对象,并且把尚且存活的对象复制到Survivor区。然后整理Survivor的两个区。这种方式的GC是对新生代的Eden区进行,不会影响到年老代。因为大部分对象都是从Eden区开始的,同时Eden区不会分配很大,所以Eden区的GC会频繁进行。因而,一般在这里需要使用速度快,效率高的算法,使Eden能尽快空闲出来。

 

年老代GC(Full GC):Full GC指发生在年老代的GC,出现了Full GC一般会伴随着至少一次的Minor GC(年老代的对象大部分是Minor GC过程中从新生代进入老年代),比如:分配担保失败。Full GC的速度一般会比Minor GC 的速度慢10倍以上。当年老代内存不足或者显式调用System.gc()方法时,会触发Full GC。

 

次收集:当新生代堆空间紧张时会被触发,相对于全收集而言,收集间隔较短。

全收集:当年老代或者持久代堆空间满了,会触发全收集操作。也可以使用System.gc()方式来显式的启动全收集。全收集一般根据堆大小的不同,需要的时间不尽相同,但一般会比较长。不过,如果全收集时间超过3到5秒钟,那就太长了。

 

分代垃圾收集器

 

新生代收集器:serial,  ParNew,   parallel scavenge

年老代收集器:CMS(coucurrent Mark sweep),  Serial Old , parallel Old

新老通吃收集器:G1 (gabage first)

下面具体说下各种收集器。

新生代收集器

1.串行收集器(Serial)

Serial收集器是Hotspot运行在Client模式下的默认新生代收集器,它的特点是只用一个CPU/一条收集线程去完成GC工作,且在进行垃圾收集时必须暂停其他所有的工作线程(Stop the world,后面简称 STW)。可以用-XX:+UseSerialGC打开。

虽然是单线程收集,但是它却是简单而高效的。在VM管理内存不大的情况下(收集几十M~一两百M的新生代),停顿时间完全可以控制在几十毫秒~一百毫秒之间。

2.并行收集器(ParNew)

ParNew收集器其实是前面Serial的多线程版本,除使用多线程进行GC外,包括Serial可用的所有控制参数,收集算法,STW,对象分配规则,回收策略等都与Serial完全一样(也是VM启用CMS收集器-XX:+UseConcMarkSweepGC的默认新生代收集器)。

由于处在多线程切换的开下,ParNew在单CPU的环境中比不上Serial,且在通过超线程技术实现的两个CPU的环境中也不能100%保证能超越Serial。但随着可用的CPU数量的增加,收集效率肯定也会大大增加(ParNew收集线程数与CPU的数量相同,因此在CPU数量过大的环境中,可用-XX:+ParallelGCthreads=<N>参数控制GC线程数,一般就是CPU核心数量)。

相对Serila收集器,ParNew主要解决的是安全点时间长短问题

如果年老代如果有CMS收集器,那新生代默认的次收集器为ParNew,但是也可以修改为Serial收集器。

 

3.Parallel Scavenge收集器

与ParNew类似,Parallel Scavenge也是采用复制算法,也是并行多线程收集器。但是与其他收集器关注尽可能缩短垃圾收集时间不同,Parallel Scavenge更关注系统的吞吐量。

系统吞吐量=CPU运行用户代码时间 / (CPU运行用户代码时间+垃圾收集时间)

停顿时间越短就越适用于用户交互的程序--良好的响应速度能提升用户的体验;而高吞吐量则适用于后台计算而不需要太多交互的任务--可以最高效率的利用CPU时间,尽快的完成程序的运行任务。

Parallel Scavenge提供了如下参数设置系统吞吐量:

Parallel Scavenge参数描述
-XX:MaxGCPauseMillis(毫秒数)收集器将尽力保证内存回收话费的时间不超过设定值,但是如果太小将会导致增加GC的频率
-XX:GCTimeRatio(整数:0<GCTimeRatio<100)是垃圾收集时间占总时间的比率。
XX:+UseAdaptiveSizePolicy

启用GC自适应的调节策略:不再需要手工指定-Xmn,

-XX:SurvivorRatio,

-XX:PretenureSiseThreshold

等细节参数,VM会根据当前系统的运行情况收集性能监控信息,动态调整这些参数以提供最合适的停顿时间或最大的吞吐量

  

 

老年代收集器

4.Serial Old收集器

Serial Old是Serial收集器的老年代版本,同样是单线程收集器。使用“标记-整理”算法:

5.Parallel Old收集器

Parallel Old是Parallel Scavenge收集器的老年代版本,使用多线程和“标记-整理”算法,吞吐量优先,主要与Parallel Scavenge配合,在注重吞吐量及CPU资源的敏感系统内使用。

 

6.CMS收集器

CMS(Concurrent Mark Sweep)收集器是一款真正具有划时代意义的收集器,一款真正意义上的并发收集器,虽然现在已经有了理论意义上表现更好的G1收集器,但现在主流互联网企业线上选用的仍是CMS(如淘宝,微店)。

CMS是一种以获取最短回收停顿时间为目标的收集器。(CMS又称为多并发低暂停的收集器),基于“标记-清除”算法实现,整个GC过程分为以下4个步骤:

  1. 初始标记(CMS initial mark)
  2. 并发标记(CMS concurrent mark:GC Roots Tracing过程)
  3. 重新标记(CMS remark)
  4. 并发清除(CMS concurrent sweep:已死对象将会就地释放,注意此处没有压缩)

其中1,3两个步骤(初始标记,重新标记)仍需STW,但初始标记仅标记一下GC Roots能直接关联到的对象,速度很快;而重新标记则是为了修正并发标记期间因用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,虽然一般比初始标记阶段稍长,但要远小于并发标记时间。

1.CMS默认启动的回收线程数=(CPU数目+3) / 4

当CPU数大于4时,GC线程最多占用不超过25%的CPU资源,但是当CPU的数量小于等于4时,GC线程可能就会过多的占用用户的CPU资源,从而导致应用程序变慢,吞吐量降低。

 

2.无法处理浮动垃圾,可能出现Promotion Failure,Concurrent Mode Failure而导致另一次Full GC的产生:浮动垃圾指的是在CMS并发清理阶段用户线程运行而产生的新垃圾。由于在GC阶段用户线程还需运行,因此还需要预留足够的内存空间给用户线程使用,导致CMS不能像其他收集器那样等到老年代几乎填满了再进行收集。因此CMS提供了-XX:CMSInitiatingOccupancyFraction参数来设置GC的触发百分比(以及-XX:+UseCMSInitiatingOccupancyOnly来启动该触发百分比)。当年老代的使用空间超过该比例后CMS就会被触发(JDK1.6之后默认92%)。但当CMS运行期间预留的内存无法满足程序需要,就会出现上述Promotion Failure等失败,这时VM将启动后备预案:临时启用Serial Old收集器来重新执行Full GC(CMS通常配合大内存使用,一旦大内存转入串行的Serial GC,那停顿的时间就是大家都不愿看到的了)

 

3.最后,由于CMS采用“标记-清除”算法实现,可能会产生大量内存碎片,内存碎片过多可能会导致无法分配大对象而提前触发Full GC。因此CNS提供了-XX:+UseCMSCompactAtFullCollection开关参数,用于在Full GC后再执行一个碎片整理过程。但内存整理是无法并发的,内存碎片问题虽然没有了,但停顿时间也因此变长了。因此CMS还提供了另外一个参数-XX:CMSFullGCBeforeCompaction用于设置在执行N次不进行内存整理的Full GC后,跟着来一次带整理的(默认为0:每次进入Full GC都进行碎片整理)。

 

7.分区收集器-G1收集器

G1(Garbage First)是一款面向服务端应用的收集器,主要目标用于配备多颗CPU的服务器治理大内存。

--XX:+UseG1GC启用G1收集器。

与其他基于分代的收集器不同,G1将整个JAVA堆划分为多个大小相等的独立区域(Region),虽然还保留着新生代和老年代的概念,但新生代和老年代不再是物理隔离的了,他们都是一部分Region(不需要连续)的集合。

 

 

重点:各收集器之间的配合关系网

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值