JVM G1

设计架构的重要思想

  • 分治
  • 分层

官方地址:https://www.oracle.com/technical-resources/articles/java/g1gc.html

吞吐量G1比PS降低10%~15%

追求耗时少,200ms内有响应,用G1

追求throughput,用Parallel

G1原理模型

humongous object

  • 超过单个region50%

GC何时触发

YGC

  • Eden空间不足
  • 多线程并行执行

FGC

  • Old空间不足
  • system.gc()

G1特点

  • 并发收集
  • 压缩空闲空间不会延长GC的暂停时间
  • 更易预测的GC暂停时间
  • 适用不需要实现很高的吞吐量的场景
  • 动态新老年代比例:5%~60%,不需要手工指定
  • G1预测停顿时间的基准

Card Table

  • YGC的时候,需要扫描整个Old区域,效率非常低,所以Jvm设计了CardTable
  • 如果一个CardTable中有对象指向Y区,将其设置为Dirty,下次扫描时,只需要扫描Dirty的Card Table
  • 在结构上,Card Table用Bitmap实现

G1的内存区域不是固定的Eden或者Old

G1基本概念

CSet

CSet = Collection Set

  • 一组可被回收的分区的集合
  • 在CSet中存活的数据会在GC过程中被移动到另一个可用分区
  • CSet中的分区可以来自Eden空间、survivor空间或者老年代
  • Cset会占用不到整个堆空间的1%大小

Rset

RememberedSet(G1高效回收的关键

  • Region中都有一个HashSet(Rset),记录其他对象对本对象的引用
  • 回收高效,占用空间变大,空间换时间

G1中的MixedGC

相当于一个CMS

XX:InitiatingHeapOccupacyPercent
  • 默认值45%
  • 当O超过这个值时,启动MixedGC

MixedGC过程

  • 初始标记stw
  • 并发标记
  • 最终标记(重新标记)
  • 筛选回收stw(并行)

初始标记

并发标记

最终标记

并行筛选回收(筛选垃圾最多的region进行回收)

如果G1产生FCG,应该怎么做

  • 扩内存
  • 提高CPU性能(回收得快,业务逻辑产生对象速度固定,垃圾回收快,内存空间大)
  • 降低MixedGC触发的阈值,让MixedGC提早发生(默认45%)

阿里多租户Jvm

  • 每租户空间
  • session based GC

并发标记算法

在标记对象过程中,对象的引用关系正在发生改变

三色标记

  • 白色,未被标记的对象
  • 灰色,自身被标记,成员变量未被标记
  • 黑色,自身和成员变量均已标记完成

漏标

A指向D,B指向D的引用消失了

产生漏标

漏标指的是,live object,由于没有遍历到,被当成garbage回收

  • 标记进行时增加了一个黑到白的引用,如果不重新处理黑色,会漏标
  • 标记进行时删除了灰对象对白对象的引用,这个白对象可能被漏标

漏标解决方法

incremental update(CMS采用方案

  • 增量更新,关注应用的增加,把黑色重新标记为灰色,下次重新扫描属性

SATB snapshot at the beginning(G1采用方案

  • 关注引用删除,当B->D消失时,要把这个引用推到GC的堆栈,保证D还能被GC扫描到

为什么G1使用SATB

  • 灰色->白色,引用消失时,如果没有黑色指向白色
  • 引用会被push到堆栈,下次扫描时拿到这个引用,由于RSet的存在
  • 不需要扫描整个堆区查找指向白色的引用,效率比较高
  • SATB配合RSet,完美搭配

Rset与赋值效率

  • 由于RSet的存在,每次给对象赋引用时候,就得做一些额外操作
  • 在Rset中做一些额外的记录(在GC中称为写屏障)

写屏障(不是内存屏障)

No Sivler Bullet

论读书
睁开眼,书在面前
闭上眼,书在心里
原文地址:https://www.cnblogs.com/YC-L/p/14418930.html