JVM 垃圾回收器 ZGC线程

JVM 垃圾回收器 ZGC线程

学习ZGC,主要通过学习ZGC设计与实现书籍,并以博客的形式记录学习内容
ZGC主要靠后台线程执行,后台线程包括控制线程和工作线程。控制线程是主要控制垃圾回收的触发、执行;工作线程是真正执行垃圾回收具体的任务,比如对象的标记、转移。

JVM线程

在这里插入图片描述

控制线程

ZGC新引入3大基础线程分别为ZDirector、ZDriver、ZStat。

  • ZDirector:控制什么时候启动垃圾回收。
  • ZDriver:控制垃圾回收执行的步骤,ZGC垃圾回收一共分为10步,这10步是串行执行的。
  • ZStat:收集JVM在运行过程中回收垃圾时各个阶段的数据,同时控制统计信息输出。

3大基础线程的设计思路类似,都继承于基类ConcurrentGCThread,基类提供的功能主要有:

  • 创建并启动线程
  • 重载虚函数run()

在这里插入图片描述
3大基础线程都是主动轮询的,查询是否可以执行对应的业务逻辑,都是通过run_service()来完成轮询的。
在这里插入图片描述
ZDirector和Zstat通过时钟来控制是触发发业务逻辑。

  • ZDirector每100ms检查1次是否需要触发,如果可以触发则发送消息给ZDriver启动垃圾回收
  • ZStat每1s检查1次是否需要触发,如果可以触发则启动收集运行信息,并输出收集到的运行信息
  • ZDriver的主循环判断线程是否终止,如果不终止则会一直循环,在循环内部使用消息的通知机制,如果ZDirector有消息到达则执行垃圾回收,如果没有消息到达则等待。

时钟控制器

ZGC的时钟控制器运行后,在满足条件时会成功地返回,不满足条件时会一直等待,等待将导致线程放弃执行,并让出CPU。
在这里插入图片描述

ZDirector

ZDirector提供了4种触发回收的方法,分别时基于固定时间间隔、预热规则、分配速率、主动触发规则
在这里插入图片描述
ZDirector虽然实现为并发线程,但在ZGC种只有一个,所以ZDirector不会涉及并发问题。

ZStat

统计线程为每1s收集信息一次,但是在输出时统计线程会把收集到的数据进行聚合,目前提供了3种粒度的统计数据,分别为过去10s,过去10min和过去10h的统计数据。
这3个粒度的数据可以定义为:

  • 统计线程最近10次运行的数据
  • 60个过去10s的数据
  • 60个过去10min的数据
    所以实际只存储130个数据

ZStat在ZGC中也只有一个,不会设计并发问题。

消息触发

ZDriver是通过消息触发执行的。
在进行消息处理时,ZGC设计了两种消息处理方式:同步垃圾回收和异步垃圾回收。

  • 同步垃圾回收主要是保证垃圾回收一定会发生,并且直到垃圾回收完成才会继续执行。
  • 异步垃圾回收则是为了实现更多的吞吐量,如果有多个异步消息在同一个垃圾回收周期到达,则只有一个请求被处理,即垃圾回收只会被执行一次。

ZGC中触发垃圾回收的主要是由ZDirector产生的异步消息。ZMessagePort对消息进行处理,经过消息处理器ZMessagePort处理后,如果有垃圾回收的请求,则通知ZDirver启动垃圾回收,如果没有请求ZDriver则等待。
在这里插入图片描述
ZDriver定义了垃圾回收的步骤,一共分为10步。
在这里插入图片描述

VMThread

VMThread不是ZGC引入的,它在JVM中已经有很长的历史了。VMThread的主要目的是提供一个串行执行任务的地方。
在整个JVM中有许多事件不能并发执行,只能串行执行。VMThread是为了串行执行映入的,当要执行垃圾回收时,告诉VMThread把其他的线程都暂停掉,然后VMThread执行请求的业务。
在VMThread线程设计和实现有以下3个注意点:

  1. 如何进入安全点
    安全点指让待暂停的线程在某一时刻全部暂停。不同的线程进入的方法不同。

在这里插入图片描述

  • 解释执行的线程,Java代码被编译成字节码,线程对字节码解释执行。在JVM中解释方法的实现主要通过模板解释器完成,在模板解释器中,每一个字节码对应一段可以执行的机器代码。当解释线程要进入安全点的时候,会把对应函数换成进入安全点的函数。
  • 编译执行的线程,插入一些安全检查的指令,会轮询全局的状态,如果发现满足条件,让出CPU,从而完成线程暂停,并在安全点推出时通知线程继续执行代码。
  • 执行本地代码(native code)的线程,本地代码访问的内存空间和Java堆空间不是一个,即它不能直接访问Java对象,所以VMThread是不需要等待线程暂停的,也就是说VMThread和政治执行本地代码的线程可以并发执行。但是如果从本地代码切换到Java代码执行时,就需要让这个线程暂停,使这个线程进入安全状态的方式是:让VMThread设置一个标志位,当线程从本地代码切换到Java执行时判断一下标志位,如果发现已经设置,就让自己暂停。
  1. 全部暂停和部分暂停
    在JDK10之前,VMThread进入安全点执行业务之前,需要STW,等待上述3类线程全部暂停之后才会执行业务。等待全部线程暂停执行,这是很花费时间的,所以在JDK10中引入JEP312Thread-Local HandShake,该项目实现单个线程暂停,而不是暂停所有线程。
  2. ZGC的控制线程如何暂停
    ZGC的ZDirector和ZStat不会访问Java对象,所以在垃圾回收的执行过程中不会暂停。ZDriver是控制垃圾回收线程工作的,在垃圾回收工作线程启动后(即要求进入安全点之后),通过通知/等待机制实现暂停/恢复。

工作线程

工作线程是真正执行垃圾任务的线程。

  • 并行工作线程:并行执行。指的是在垃圾回收时,首先执行STW,然后多个GC工作线程并行工作,然后多个GC线程并行工作。在ZGC中有3步是并行执行的,分别为初始标记、再标记和转移根对象。
  • 并发工作线程:并发执行。指的是在垃圾回收时,除了上面3步并行执行外,其余都是可以并发地和应用程序同时执行。
    ZGC重用了参数ParallelGCThreads和ConcGCThreads来设置并行工作线程和并发工作线程数目,如果用户没用显式地设置这两个参数,ZGC会启发式地推断这两个参数。
    ParallelGCThreads:CPU的60%并向上取整。
    ConcGCThreads:CPU的12.5%并向上取整。
    ZGC还提供了动态调整并发工作线程的能力。实际中可能还存在内存使用紧张的情况,会增大并发工作线程得到数目。

垃圾回收触发的时机

  1. 基于固定实际间隔触发
  2. 预热规则触发
    当发现堆空间使用率达到10%、20%、30%会主动触发垃圾回收,ZGC设计前3次垃圾回收可由预热规则触发,也就是次数超过3次,预热规则将不再生效
  3. 根据分配速率
  4. 主动触发
  5. 阻塞内存分配请求触发
  6. 外部触发
  7. 云数据分配触发
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值