java虚拟机

Minor GC与Full GC分别在什么时候发生?

2018-07-17  本文已影响89人  CodeKing2017

Minor GC:

Eden区域满了,或者新创建的对象大小 > Eden所剩空间

CMS设置了CMSScavengeBeforeRemark参数,这样在CMS的Remark之前会先做一次Minor GC来清理新生代,加速之后的Remark的速度。这样整体的stop-the world时间反而短

Full GC的时候会先触发Minor GC。执行Minor GC需要注意:

>>A.当JVM无法为一个新的对象分配空间时会触发Minor GC,比如当Eden区满了。所以分配率越高,越频繁执行Minor GC。

>>B.内存池被填满的时候,其中的内容全部会被复制,指针会从0开始跟踪空闲内存。Eden和Survivor区进行了标记和复制操作,取代了经典的标记、扫描、压缩、清理操作。所以Eden 和Survivor 区不存在内存碎片。写指针总是停留在所使用内存池的顶部。

>>C.执行Minor GC操作时,不会影响到永久代。从永久代到年轻代的引用被当成GC roots,从年轻代到永久代的引用在标记阶段被直接忽略掉。

>>D.质疑常规的认知,所有的Minor GC都会触发“全世界的暂停(stop-the-world)”,停止应用程序的线程。对于大部分应用程序,停顿导致的延迟都是可以忽略不计的。其中的真相就是,大部分Eden 区中的对象都能被认为是垃圾,永远也不会被复制到Survivor 区或者老年代空间。如果正好相反,Eden 区大部分新生对象不符合GC条件,Minor GC 执行时暂停的时间将会长很多。

Major GC:清理永久代,但是由于很多MojorGC 是由MinorGC 触发的,所以有时候很难将MajorGC 和MinorGC区分开。

FullGC:是清理整个堆空间—包括年轻代和永久代。FullGC 一般消耗的时间比较长,远远大于MinorGC,因此,有时候我们必须降低FullGC 发生的频率。

Minor GC后存活的对象晋升到老年代时由于悲观策略的原因,有两种情况会触发Full GC, 1种是之前每次晋升的对象的平均大小 > 老年代剩余空间

1种是Minor GC后存活的对象超过了老年代剩余空间。这两种情况都是因为老年代会为新生代对象的晋升提供担保,而每次晋升的对象的大小是无法预测的,所以只能基于统计,1个是基于历史平均水平,一个是基于下一次可能要晋升的最大水平。这两种情况都是属于promotion failure

CMS失败,发生concurrent mode failure会引起Full GC,这种情况下会使用Serial Old收集器,是单线程的,对GC的影响很大。concurrent mode failure产生的原因是老年代剩余的空间不够,导致了和gc线程并发执行的用户线程创建的大对象(由PretenureSizeThreshold控制新生代直接晋升老年代的对象size阀值)不能进入到老年代,只要stop the world来暂停用户线程,执行GC清理。可以通过设置CMSInitiatingOccupancyFraction预留合适的CMS执行时剩余的空间

新生代直接晋升到老年代的大对象超过了老年代的剩余空间,引发Full GC。注意于promotion failure的区别,promotion failure指的是Minor GC后发生的担保失败

Perm永久代空间不足会触发Full GC,可以让CMS清理永久代的空间。设置CMSClassUnloadingEnabled即可

System.gc()引起的Full GC,可以设置DisableExplicitGC来禁止调用System.gc引发Full GC

上一篇下一篇

猜你喜欢

热点阅读