G1
-XX:+UseG1GC
概念
jdk8中也支持G1垃圾回收器,在JDK9时默认使用的是G1垃圾回收器。它适用于堆内存>8G 的场景。
G1垃圾收集器让我们忘记年龄分代的概念,但其实它还是有年龄分代的概念
G1将一整块堆内存,平均分成了默认2048个独立区域Region,JVM目标是不超过2048个Region(JVM源码里TARGET_REGION_NUMBER 定义),实际可以超过该值,但是不推荐。
其中年轻代默认占总堆内存的5%,最大占60%,这其中Eden区域Survivor区的比例还是8:1:1
首先创建对象,对象都是存放在Eden区的Region中,当放满后可能会触发MinorGC,将存活对象使用复制算法移动到Survivor区,然后程序继续运行,存活对象在Survivor区来回复制,当分代年龄达到15后就复制到老年代的Region中。对于大对象直接存放在Humongous区的Region中,当一个对象占用内存大于了Region内存是50%就是大对象。
从上面的执行过程中我们可以发现,每经过一次GC,Region的角色都会动态改变,可能从Old区变为空闲区,再变为Eden区。
垃圾收集过程
和CMS垃圾回收器类似,也有初始标记、并发标记。区别是CMS叫重新标记,G1叫最终标记,但其实是一样的;还有就是G1是筛选回收是STW的,充当了CMS的并发清理和并发重置阶段。
-
初始标记
-
并发标记
-
最终标记
G1是使用的本地快照SATB的方式来处理漏标问题的
-
筛选回收
G1会对要回收的Region进行回收价值和成本计算, 在后台维护一个回收优先级列表。再根据用户期望的GC最大停顿时间(
-XX:MaxGCPauseMillis
默认200ms)来进行回收内存,在回收时会优先回收存活对象较少的Region,因为如果存活对象少,在采用复制算法将存活对象复制到另一个Region中耗时要少。如果一个Region100的对象,其中95个对象都是存活对象,那么复制的意义就不大,而且复制95个对象很耗时。垃圾回收时如果达到了GC最大停顿时间那么剩余的Region就会等下一次GC再去进行回收。
垃圾收集分类
-
MinorGC
年轻代默认占总堆内存的5%,其中还有Survivor区,大概Eden区初始占4%左右。当Eden区的Region放满对象后可能就会触发一次MinorGC。
因为它会计算这一次如果进行MinorGC过程中大概STW的耗时,默认STW最大停顿时间是200ms,如果这一次只需要50ms