常见垃圾回收期
一、分区模型介绍
(1)Serial 、Serial Old 、 Parallel 、 Parallel Old 、 ParNew 、CMS这些垃圾收集器都是基于分代收集理论,即将内存区域按照存储对象的不同分为年轻带、老年代和元空间。
(2)G1 和 ZGC 逐渐淡化了这种分代的概念,堆被划分为一组大小相等的堆区域,每个堆区域都有一个连续的虚拟内存范围。 这在内存使用方面提供了更大的灵活性。G1的堆内存分配如下:
(3) G1在淡化分代理论上还不是很彻底, G1保留了年轻代和老年代的概念,但不再是物理隔阂了,它们是(可以不连续)Region的集合。
(4)G1同时注重吞吐量和响应时间
-XX:G1HeapRegionSize=size 将堆分成若干个等大的区域,默认2048个
-XX:MaxGCPauseMillis=time 最大暂停时间,默认200ms,尽最大努力保证该时间
(5)G1整体上是 标记+整理 算法,两个区域之间是 复制 算法
(6)G1为java9默认的垃圾回收器,在java8还不稳定
美团面试题:G1在jdk8中为啥不稳定
1、在JDK 8u40之前,G1 只能依赖 full GC 来卸载类,而G1不一定出现full GC(详见本文第四部分),所以会出现类无法卸载的问题。
2、在JDK 8u40中, G1 实现了没有full GC 也可以进行类卸载:所有对象都经过并发标记后,就能知道哪些类不再被使用,当一个类加载器的所有类都不再使用,则卸载它所加载的所有类(主要针对自定义的类加载器),从此 G1 成为功能齐全的垃圾收集器,准备成为默认。参考:
二、 G1个阶段详细介绍
2.1 年轻代垃圾回收
同CMS,会STW
2.2 年老代垃圾回收
2.2.1 初始标记 (initial mark,STW)
1、当老年代占用堆空间比例达到阈值时(默认45%),进行初始标记;
2、初始标记做了什么?-->进行年轻代回收,并对GC Root 进行初始标记,会STW。
2.2.2 并发标记(Concurrent Marking)
同CMS的并发标记
2.2.3 最终标记(Remark,STW)
同CMS的重新标记
2.2.4 筛选回收(Cleanup,STW)
首先对各个Region的回收价值和成本进行排序,根据用户所期望的GC停顿STW时间(可以用JVM参数 -XX:MaxGCPauseMillis指定)来制定回收计划 。
举个例子 老年代此时有1000个Region都满了,但是因为根据预期停顿时间,本次垃圾回收可能只能停顿200ms,那么通过之前回收成本计算得知,可能回收其中800个Region刚好需要200ms,那么就只会回收800个Region(Collection Set,要回收的集合),尽量把GC导致的停顿时间控制在我们指定的范围内。
这个阶段 G1因为内部实现太复杂暂时没实现并发回收,所以会STW。到了ZGC,Shenandoah就实现了并发收集,Shenandoah可以看成是G1的升级版本。
三、G1中的跨代引用
如何知道年轻代被年老代引用:卡表+RememberSet
四、Full GC
- SerialGC
新生代内存不足发生的垃圾收集 - minor gc
老年代内存不足发生的垃圾收集 - full gc
- ParallelGC
新生代内存不足发生的垃圾收集 - minor gc
老年代内存不足发生的垃圾收集 - full gc
- CMS
新生代内存不足发生的垃圾收集 - minor gc
老年代内存不足-Major GC
- G1
新生代内存不足发生的垃圾收集 - minor gc
老年代内存不足-Major GC
4.1 对Full GC的理解
1、对于年轻代,各垃圾回收器都是minor gc;
2、对于年老代,串行、并行垃圾回收器都是full GC;
3、对于CMS,当在进行垃圾回收期间并且出现内存不足时,会转为串行回收,此时才是full GC,不然仅是Major GC
4、对于G1,当在进行垃圾回收期间并且出现内存不足时,会转为串行回收,此时才是full GC,不然仅是Mixed GC
4.2 GC的分类
- 新生代收集(Minor GC/Young GC):只针对新生代的垃圾收集。
- 老年代收集(Major GC/Old GC):只针对 老年代的垃圾收集。
- 混合收集(Mixed GC):对新生代、老年代的垃圾进行收集。
- 整堆收集(Full GC):对整个堆空间进行收集,包括:新生代、老年代、运行时常量池(jdk1.8之前还包括方法区)。
一个面试题:年轻代对象进入年老代的途径有哪几个?
1、在s0、s1回收次数超过15次会进入年老代;
2、大对象直接进入年老代(超过survivor一半即认为是大对象)
3、survivor区垃圾回收后仍然放不下的对象,会直接放在年老代