OpenJDK16 ZGC 源码分析(三)读屏障Load Barrier

1. 简介

对于并发GC来说,最复杂的事情在于GC worker在标记-整理,而Java线程(Mutator)同时还在不断的创建新对象、修改字段,不停的更新对象引用关系。因此并发GC一般采用两种策略Incremental Update(增量更新、CMS) 和SATB(snapshot at beginning、G1) ,两种策略网上介绍文章很多,此处不再赘述。

SATB重点关注引用关系的删除,可以参考我之前的博客JVM G1 源码分析(四)- Dirty Card Queue Set,而Incremental Update重点关注引用关系的增加。

而ZGC并没有采取类似方式,而是借助读屏障、colored pointer来实现并发标记-整理。

2. 原理

2.1 什么是Load Barrier

  • 一小段在最佳位置由JIT注入的代码
    • 从堆中加载一个对象引用时
  • 检查这个引用是否是bad color
    • 如果是,则自愈

2.2 Load Barrier的触发

从堆中加载对象引用时触发load barrier。

// 从堆中加载一个对象引用,需要load barrier
String n = person.name;	
// 不需要load barrier,不是从堆中加载
String p = n;			
// 不需要load barrier,不是从堆中加载
n.isEmpty();			
// 不需要load barrier,不是引用类型
int age = person.age;	

当引用类型n被赋值修改后,在下一次使用n前,会测试n的染色指针是否为good。此时测试为bad color可知n的引用地址进行过修改,需要自愈。

触发load barrier的伪代码如下:

// 从堆中加载一个对象引用,需要load barrier
String n = person.name;	
if (n & bad_bit_mask) {
   
	slow_path(register_for(n), address_of)
}

对应的汇编代码:

// String n = person.name;	
mov 0x10(%rax), %rbx
// 是否bad color
test %rbx, (0x16)%r15
// 如是,进入slow path
jnz slow_path

2. 源码分析

2.1 掩码

zGlobals.hpp

//
// Good/Bad mask states
// --------------------
//
//                 GoodMask         BadMask          WeakGoodMask     WeakBadMask
//                 --------------------------------------------------------------
//  Marked0        001              110              101              010
//  Marked1        010              101              110              001
//  Remapped       100              011              100              011
//

// Good/bad masks
extern uintptr_t  ZAddressGoodMask;
extern uintptr_t  ZAddressBadMask;
extern uintptr_t  ZAddressWeakBadMask;

zAddress.inline.hpp

inline bool ZAddress::is_null(uintptr_t value) {
   
  return value == 0;
}

inline bool ZAddress::is_bad(uintptr_t value) {
   
  return value & ZAddressBadMask;
}

inline bool ZAddress::is_good(uintptr_t value) {
   
  return !is_bad(value) && !is_null(value);
}

从以上两段代码可以很清晰看出,colored pointer的状态是Good/WeakGood/Bad/WeakBad由GoodMask及BadMask来测定。

同时,GoodMask、BadMask由GC所处的阶段决定。

void ZAddress::set_good_mask(uintptr_t mask) {
   
  ZAddressGoodMask = mask;
  ZAddressBadMask = ZAddressGoodMask ^ ZAddressMetadataMask;
  ZAddressWeakBadMask = (ZAddressGoodMask | ZAddressMetadataRemapped | ZAddressMetadataFinalizable) ^ ZAddressMetadataMask;
}

void ZAddress::initialize() {
   
  ZAddressOffsetBits = ZPlatformAddressOffsetBits();
  ZAddressOffsetMask = (((uintptr_t)1 << ZAddressOffsetBits) - 1) << ZAddressOffsetShift;
  ZAddressOffsetMax = (uintptr_t)1 << ZAddressOffsetBits;

  ZAddressMetadataShift = ZPlatformAddressMetadataShift();
  ZAddressMetadataMask = (
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值