java final 垃圾回收_新的Java垃圾回收机制ZGC 简介

垃圾回收是Java的一项重要机制,是二月份的一项学习计划之一。

ZGC是一种较新的垃圾回收机制,在JDK11中实验性引入,看了R大的几篇文章,依然不懂,之后发现了一篇介绍地比较易懂的文章:

希望对你有帮助。

英语文章,特此翻译总结一下,以便后续我自己迅速浏览:

ZGC的背景:

GC需要了解一个概念,S-T-W: Stop the world,即整个应用程序暂停,等待GC完成。

这个时间内,应用程序暂停,因此需要越短越好。

那么,有哪些将STW变短的方法?

GC可以在压缩时使用多个线程。(并行压缩)

压缩工作也可以分解为多个阶段(增量压缩)。

将堆压缩,却不停止正在运行的应用程序(或只是短时间停止)(并发压缩)。

完全不压缩。

这里的压缩,指的就是:

moving the still-alive objects to the start (or some other region) of the heap.

将依然存活的对象移动到堆的起始端(或者其他区域)

ZGC在STW很短的时间下,需要解决的问题

需要把一个对象拷贝到另一个内存地址,同时其他线程还可以对老对象进行读取与修改。

拷贝成功以后,需要把所有老的引用更新。

ZGC性能评测:

jquUba.jpg

很快,很强,接下来我们看一下ZGC的设计思路。

load barrier

ZGC使用read barrier,即对指向堆的引用进行读取时,会发生read barrier,比如

obj.field //加载堆中对象的引用,触发load barrier,干什么事儿下文有介绍

ZGC不使用write barrier:

obj.field = value //不使用write barrier,此时不会触发load barrier

注意,这都是针对堆中的引用。

着色指针

ZGC对于引用指针使用了一些标记,在地址的42~45位,如下:

6 4 4 4 4 4 0

3 7 6 5 2 1 0

+——————-+-+—-+———————————————–+

|00000000 00000000 0|0|1111|11 11111111 11111111 11111111 11111111 11111111|

+——————-+-+—-+———————————————–+

| | | |

| | | * 41-0 Object Offset (42-bits, 4TB address space)

| | |

| | * 45-42 Metadata Bits (4-bits) 0001 =

Marked0

| | 0010 =

Marked1

| | 0100 =

Remapped

| | 1000 =

Finalizable

| |

| * 46-46 Unused (1-bit, always zero)

|

* 63-47 Fixed (17-bits, always zero)

Marked0,Marked1,Remapped,Finalizable,四位元数据。

内存分区

将内存分解成3种大小的Region(Page):

small:2MB,存放256k大小以内的对象

medium:32MB,存放最大4MB的对象

large:2MB * N,只能存放一个大于4MB的对象(large region最小只有6MB,比medium的region还小)

ZGC可以区分物理内存与虚拟内存,可以使用4TB的虚拟内存以及最大堆大小的物理内存。在物理内存中找到连续的32MB空间是不容易的,因此ZGC做了从物理内存到虚拟内存的映射。

ZGC能够将这些非连续的物理页面映射到单个连续的虚拟内存空间。如果这是不可能的,我们就会耗尽内存。

在Linux上,物理内存基本上是一个匿名文件,只存储在RAM中(而不是存储在磁盘上),ZGC使用memfd_create来创建它。然后可以使用ftruncate扩展该文件,允许ZGC将物理内存(=匿名文件)扩展到最大堆大小。然后将物理内存映射到虚拟地址空间中。

Marking & Relocating objects

标记与重新分配,是GC的2个主要阶段

标记阶段:标记所有可到达的对象。

在这个阶段结束时,我们知道哪些对象仍然存在,哪些对象是垃圾。

ZGC将此信息存储在每个内存page的所谓实时地图(live map)中。实时映射是一个位图,用于存储给定索引处的对象是否可以高可达和/或最终可达(对于具有finalize方法的对象)。这里的实时地图是一个位图,用于存储给定索引处的对象,是否strongly-reachable and/or final-reachable(for objects with afinalize-method).

在标记阶段,应用程序线程中的load-barrier将未标记的引用推送到线程局部标记缓冲区。只要此缓冲区已满,GC线程就可以获得此缓冲区的所有权,并以递归方式遍历此缓冲区中的所有可到达对象。在应用程序线程中标记只是将引用推送到缓冲区,GC线程负责遍历对象图并更新实时映射。

重分配阶段:

在进行标记后,GC统计了垃圾最多的若干内存page(即上文的region),将它们称作:relocation set。对于这些page,GC需要将它们中所有的存活对象进行重新分配,并生成一个映射转发表,存放被relocated的对象的新地址。

一个对象的重分配可能由GC线程完成,也可能是应用程序线程(比GC线程更早访问对象时,load barrier进行)。当这两个线程同时尝试重分配同一个对象时,通过原子性的CAS操作,ZGC会找到第一个尝试的线程,该线程完成relocate。

完成relocate(GC线程走完所有的relocation set)之后,load barrier会将指向relocation set中的引用修正为新的地址。即Remapping

这篇文章写到这里,我依然是一头雾水,于是去找了另1篇文章

以及1份官方PPT:

让我们再重温一下概念:

veUvU3.jpg

Load Barrier:

当从堆内存中加载引用对象时使用

观察指针的颜色

当颜色是bad color:需要进行mark/relocate/remap等措施

把颜色修改为good color(repair/heal)

针对常见情况进行了优化

绝大多数对象的引用都会是good color

这里就提到指针的颜色,其实是几个标志位的组合:

marked0,marked1:该对象是否被mark

Remapped:判断该对象是否在relocation set中

Finalizable:判断一个对象只能通过finalizer机制到达了

根据这些bit,ZGC可能会在我们获取引用前执行一些处理。

因此,它可能返回完全不同的引用。

好坏的依据,在第一篇文章里有,这里感觉不需要过多理解。

最后总结一下ZGC的三个大步骤:Mark、Relocate、Remap

Mark:寻找可到达的对象

Marking is the process when the garbage collector

determines which objects we can reach. The ones we can’t reach are considered garbage. ZGC breaks marking to

three phases:

第一阶段,S-T-W,Stop the world,ZGC找寻根引用。这个数目往往很少,因此耗时很短。

第二阶段:并发阶段,ZGC并发的从根引用出发,找寻所有的可以到达的对象,并mark它们。这一阶段中,如果load barrier感知到了未mark的对象,也会mark这个对象。(使用marked0与marked1来mark一个对象)

第三阶段:S-T-W,处理一些边缘case,如弱引用

完成之后,我们已经得知了哪些对象可以到达,

Relocation:Concurrent and Parallel

ZGC统计垃圾最多的page,放进relocation set

ZGC遍历relocation set,将它们relocate

load barrier如果访问到了需要relocate的对象,也会将其relocate

ZGC与load barrier同时访问,通过CAS方式决定谁来改变

每个page都有forward table,记录新老地址

Remapping:load barrier完成

Relocation阶段没有修改引用,因此我们会访问老的对象,甚至是垃圾,修改引用的工作是通过load barrier完成的。

这里几乎综合用到了着色指针、load barrier、relocation set等知识,参考该文章的一张图片:

4e5982ef1079ded06c535cf19e3ec55d.png

看该图,当应用程序访问一个引用,并触发了load barrier时:

首先检查着色指针的Remap位置

如果Remap = 1,不用做任何事,返回引用

如果Remap = 0,判断该引用是否在relocation set中

Remap = 0,不在relocation set中:直接返回引用

Remap = 0,在relocation set中,判断是否已经relocate

Remap = 0,在relocation set中,已经relocate:更新引用至新地址,返回

Remap = 0,在relocation set中,还未relocate:relocate该对象,返回更新过的reference

至此,GC完成,可以看出ZGC不需要大的STW阶段,而只是单个变量的访问时间变慢(通过指针颜色,判断触发GC),因此大幅提升了效率。

可能还是有一些错误,还请指出。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值