流程
1.初始标记
STW后,寻找root节点,时间较短
GC ROOT =局部变量、静态变量、常量、jni(native方法)的对象
2.并发标记
不进行STW并发进行标记,同时可能也会出现垃圾
3.重新标记
进行STW,并发的进行重新标记
4.并发清理
不进行STW,并发清理垃圾,可能出现浮动垃圾
YGC + MixedGc + serialGc
标记算法-三色标记
黑色:本身和子引用都被扫描
灰色:本身被扫描,子引用未扫描
白色:未扫描
漏标情况:
因为是并发标记,存在已经标记为黑色的对象 增加了一个新引用。
解决方案
- 增量更新-当对象引用变化是 对象被标记为灰色(CMS)
- SATB 关注的是 引用删除,把这个引用添加到GC堆栈,保证不会漏标(G1),原因,由于有RSet的存在,不需要扫描整个堆查引用,效率更高。
G1堆的分代模型(分而治之)
逻辑分区,物理不分区
将堆分为不同大小(1M,2M、4M…32M)的region区域,当G1GC 决定需要进行GC,优先清理垃圾最多的Region(Garbage-first)
这些区域分别代表Eden、Survivor、Old、Humongous区其中Humongous区,大对象区域。
特点
- 并发收集
- 压缩空闲空间不会延长GC的暂停时间
- 更易预测的GC暂停时间
- 适用不需要实现很高的吞吐量的应用
一些概念
card table
帮助垃圾回收更快,查找活着的对象
Card Table 来记录 将Region中各个对象的情况,基于bitmap实现
如果存在O区对象指向S、E区,这个对象对应的card table值就会被标记为dirty值
CSet = Collection Set
一组可被回收的分区集合
RSet = Remeber Set
记录了其他Region中的对象到本Region的引用
使得垃圾收集器不需要扫描整个堆找到谁引用了当前分区中的对象
只需要扫描Rset
问题1.如果G1产生FGC,你应该做什么?
- 扩内存
- 提高CPU性能(回收的快,业务逻辑产生对象的速度固定,垃圾回收越快,内存空间越大)
- 降低MixedGC触发的阈值,让MixedGC提早发生(默认是45%)
-XX:InitiatingHeapOccupacyPercent
G1常用参数
-XX:+UseG1GC
-XX:MaxGCPauseMillis
建议值,G1会尝试调整Young区的块数来达到这个值
-XX:GCPauseIntervalMillis ?
GC的间隔时间
-XX:+G1HeapRegionSize
分区大小,建议逐渐增大该值,1 2 4 8 16 32。
随着size增加,垃圾的存活时间更长,GC间隔更长,但每次GC的时间也会更长 ZGC做了改进(动态区块大小)
-XX:G1NewSizePercent
新生代最小比例,默认为5%
-XX:G1MaxNewSizePercent
新生代最大比例,默认为60%
-XX:GCTimeRatio
GC时间建议比例,G1会根据这个值调整堆空间
-XX:ConcGCThreads
线程数量
-XX:InitiatingHeapOccupancyPercent
启动G1的堆空间占用比例