深入解析java虚拟机:垃圾回收,ShenandoahGC及并发垃圾 回收器

2022-10-31 11:26:54 浏览数 (1)

Shenandoah GC

在Shenandoah GC之前的所有垃圾回收器都必须主动或者被动地整理老年代或者新生代,因此会导致长时间的STW,对于大型的堆,比如超过100GB,所有现存的垃圾回收器几乎都表现得很差。为了解决这些问题,Red Hat开发了一个低停顿的并发垃圾回收器,并于JEP 189贡献给了OpenJDK社区,目前Shenandoah GC仍然属于实验性特性,需要使用参数-XX: UnlockExperimentalVMOptions -XX: UseShenandoahGC开启。

Shenandoah GC的STW时间不会随堆的增大而线性增长,所以回收200GB的堆和2GB的堆的STW时间相差无几。Shenandoah GC的大部分阶段都是并发的,如图10-13所示。

图10-13 Shenandoah GC

Shenandoah GC类似于G1,也是基于Region的堆设计,但是它没有采用弱分代假设。一个特别的地方是它在移动对象时允许Mutator线程运行,即并发整理阶段(Concurrent Compact),这是它减少停顿时间的关键,也是低延时的秘诀所在。因为没有分代设计,在并发整理阶段,Shenandoah GC会清理所有可能Region。并发整理的关键技术是Brooks指针。

G1仅在STW期间才能移动对象,而Shenandoah GC可以在Mutator线程运行期间并发地重定位对象位置,它通过名为Brooks指针的技术来实现这个特性。在堆中的每个对象都有一个额外的Brooks指针字段(fwdptr),它指向这个对象,当对象移动后,它指向移动后的对象,同时将对对象的修改转发到移动后的对象上,如图10-14所示。

图10-14 fwdptr指针

移动前fwdptr指向对象本身,其他指向当前fwdptr的指针转发到正常位置,移动后fwdptr指向新对象位置,对象修改通过fwdptr转发到新对象位置上,如图10-15所示。

图10-15 fwdptr转发对象修改

通过转发指针,对象移动期间无须全局STW,只需要CAS交换指针即可。除了对象修改外,对象访问也需要借助fwdptr转发,因为如果不转发就可能读取到未更新的x、y、z值。转发对象读取和对象访问请求需要通过读屏障和写屏障来完成。代码清单10-20展示了Shenandoah GC的读屏障:

代码清单10-20 Shenandoah GC读屏障

代码语言:javascript复制
oop ShenandoahBarrierSet::read_barrier(oop src) {
if (ShenandoahReadBarrier && _heap->has_forwarded_objects()) {
// 最终对(*brooks_ptr_addr(src))解引用
return ShenandoahBarrierSet::resolve_forwarded(src);
}
return src;
}
HeapWord** ShenandoahBrooksPointer::brooks_ptr_addr(oop obj) {
// 读取obj的fwdptr,然后解引用,得到地址
return (HeapWord**)((HeapWord*) obj   word_offset());
}

Shenandoah GC要求每个对象附加一个额外的转发指针字段,这会浪费一些内存,同时读屏障也会造成比较严重的开销,因为每次对象读取都会额外执行其他指令。

ZGC

ZGC是由Oracle开发的一个低停顿的并发垃圾回收器,并于JEP 333贡献给OpenJDK社区。ZGC的目标与Shenandoah GC的目标非常相似:

控制STW时间,目标10ms以内;STW时间不会随着堆的增大而变长。

ZGC使用基于Region的堆设计,同样在移动对象过程中允许GC线程和Mutator线程一同运行。Shenandoah GC给出的解决方案是Brooks指针,而ZGC使用染色指针。

x64的硬件限制使得处理器只能使用48条地址线访问256TB的内存,ZGC为对象地址保留42位,这导致目前ZGC最大只支持4TB的内存,因为着色指针的设计,ZGC不支持32位指针也不支持压缩指针。剩下的位用于存放finalizable,remapped,marked1和marked0几个标志,如图10-16所示。

图10-16 染色指针

这些标志可以指明对象是否已经被移动、是否被标记、是否只能通过finalizer可达。除了并发移动对象外,ZGC还支持基于NUMA的CPU架构,并且能归还未使用的内存给操作系统等。目前ZGC也处于实验阶段,需要-XX: UnlockExperimentalVMOptions -XX:UseZGC开启,各式各样垃圾回收器的出现说明一个事实:GC没有“银弹”,换句话说,所有GC都不能兼具低停顿时间和低运行时开销的特性,如图10-17所示。

图10-17 “鱼”和“熊掌”不可兼得

Epsilon GC可能算一个,但是它不回收垃圾,不能用于常见应用环境。也许在遥远的未来会出现类似-XX: SelectOptimumGC的参数,可以根据用户描述的应用程序特性和环境来自动选择最合适的垃圾回收器,但是目前,开发者仍然需要根据自己的应用程序特性和运行环境手动选择最合适的GC,并适度调整GC参数,使GC与应用程序相契合。没有最好的垃圾回收器,只有最合适的选择。

本文给大家讲解的内容是深入解析java虚拟机:垃圾回收,Shenandoah GC及并发垃圾回收器

  1. 下篇文章给大家讲解的是深入解析java虚拟机:面向服务端应用程序的垃圾回收器;
  2. 觉得文章不错的朋友可以转发此文关注小编;
  3. 感谢大家的支持!

本文就是愿天堂没有BUG给大家分享的内容,大家有收获的话可以分享下,想学习更多的话可以到微信公众号里找我,我等你哦。

0 人点赞