【JVM】CMS、G1

G1

基本概念

  • card table:由于在做ygc的时候,需要找到哪些对象需要回收,那就可能需要遍历全部的old区,才能找到需要回收的对象,效率低。所以jvm设置了card table.对eden区和old区,每几个对象分为一个card。如果一个card里面有一个对象的引用指向Y区,则将card设置为dirty。再次扫描只需要扫描dirty的card。在结构上,用bitmap保存。
  • CSet=collection set。一组可被回收的分区的集合。把需要回收的region,都集合起来,叫做collection set
  • RSet=remebered set。每一个region中都有一个hashtable,记录了其他region中的对象到本对象的引用。使得垃圾回收不需要扫描整个堆,就可以知道谁使用了当前region中的对象,只需要扫描Rset

原理

逻辑上分为old、survivor、eden、以及humongous(大内存区,超过单个region50%),物理上,分为一个个region,分布在不同的内存地址上,所以每一个region不是固定的old区还是eden区了。

特点

  • 并发收集
  • 压缩空闲空间不会延长GC的暂停时间
  • 更易预测GC的暂停时间
  • 适用不需要实现很高吞吐量的场景
  • 新老年代比例在5-60%,动态的。一般不需要手动指定,也不要手动指定。这是G1预测停顿时间的基准
  • MixedGC,相当于CMS
    • 当对象占用堆到达45%,启动MixedGc
      • 过程:
        • 初始标记STW
        • 并发标记
        • 重新标记STW
        • 筛选回收STW,筛选最需要回收的region(垃圾最多的)
    • -XX:initiatingHeapOccupacyPercent可以设置阈值
  •  

并发标记算法

三色标记法

  • 白色:未被标记对象,需要回收
  • 灰色:自身被标记,成员对象未被标记
  • 黑色:自身和成员变量都完成了标记

漏标:

当A标记为黑色,B标记为灰色,D为白色。在并发标记阶段的时候,A已经标记为黑色了,但是删除了B对D的引用,且将A引用指向到了D,则产生了漏标。

漏标:本来是活着的对象,但是因为没有被标记到,就被回收了。

解决方法,2选一即可:

  1. incremental update. 增量更新,关注引用的增加。把黑色重新标记为灰色,下次重新扫描属性。(CMS用的就是这个)
  2. SATB(snapshot at the begining)。关注引用的删除。当B对D的引用删除时,要把这个引用推到GC的堆栈,保证D还能被GC扫描到(G1用的是这个)

Rset与赋值的效率

由于Rset的存在,所以每次给对象赋引用的时候,就得做一些额外的操作,在Rset中做一些额外的记录(在GC中称做写屏障,这个屏障不等于内存屏障)

面试题

  1. 如果G1产生FGC,你该干什么?(内存不够分配了,就会产生FGC)
    1. 加内存
    2. 加cpu,提高分配回收对象效率,回收的越快,可用内存越大
    3. 降低mixed GC阈值 默认45%
  2. 为什么G1用SATB
    1. 删除的引用会被放到GC的栈中,下次扫描的时候,根据GC中存的引用直接找到region,再根据RSET,就可以直接找到哪些引用了当前对象,效率较高。SATB配合RSET,浑然天成
  3. cms的内存碎片化怎么解决
    1. -XX:+UseCMSCompactAtFullCollection,在FGC时进行压缩
    2. - XX:CMSFullGCsBeforeCompaction,在多少次FGC后进行压缩
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值