垃圾回收器为什么必须要停顿下?

简介: 垃圾回收器为什么必须要停顿下?

美丽又短暂的假期居然这么快就结束了,学习的小车轮继续的滚起来吧

垃圾回收器为什么必须要停顿下?

在垃圾收集器在获取根节点这一步时必须暂停用户线程的也就是我们常说的STW,目前可达性分析算法耗时最长的查找引用链的过程已经可以做到和用户线程一起并发,但根节点枚举的获取还必须是要在一个能保证一致性的快照中才能进行。

这里说的一致性就是根节点枚举分析期间执行子系统看起来就像被冻结在某个时间点上,不会出现一边分析,根节点的对象引用关系还在不断的变化的情况。这也是导致垃圾收集过程必须停顿所有用户线程的其中一个重要原因,即便是号称停顿时间可控的CMS、G1、ZGC等,跟节点分析时也是必须要停顿的。

GC Roots

都知道JVM内对象存活判定一般用可达性分析算法,也就是说在HotSpot 使用里面维护了很多根节点(GC Roots)。

GC Roots种类:

  • 静态变量引用的对象
  • 常量引用的对象
  • 栈针本地变量表引用的对象
  • JNDI 引用的对象

什么是OopMap ?

目前主流JVM垃圾收集,在当用户线程停顿下后其实是不需要一个不漏的检查完所有的执行上下文和全局引用位置的。在HotSpot中是使用一组成为OopMap的数据结构来达到这个目的的。

当类加载动作完成时,HotSpot就会将对象内的类型、偏移量等数据计算出来,这时在垃圾收集器扫描的时候就可以直接得到这些信息了,并不需要一个不漏的从GC Roots开始查找。

借助于OopMap,虚拟机可以快速枚举GC Root引用,这就是典型的以空间换时间。但导致引用关系变化非常多,又不能生成过多的OopMap从而导致存储资源的浪费,所以又出现了安全点和安全区域。

什么是安全点?

在OopMap的帮助下,可以快速的完成GC Roots数据扫描,但可以导致引用关系变化的可能太多了,也就是说导致OopMap内容变化的指令非常多,不可能每次变化都生成对应的OopMap。

所以,在某个特定的位置来记录关系信息到OopMap,这些位置就被称为安全点。其实也就是在代码执行到达指定的位置才能够暂停进行信息收集。

举例Serial 收集器(其他收集器也差不多):

  • 单线程收集器,收集的时候会暂停所有用户线程(简称STW)
  • 客户端模式下默认收集器
  • 简单高效,是所有收集器中额外内存消耗最小的

安全点的选定:具有让程序长时间执行的特征,例如方法调用、循环跳转、异常跳转等。

怎么到达安全点?

在实际情况下,是不可能在发生垃圾收集的时候所有的线程都正好在安全点,所以就需要线程都跑到最近的安全点然后停顿下来。

有两种方案:

抢先试中断(Preemptive Suspension):(现在几乎没有用这种的了)

不需要线程的执行代码主动配合,在垃圾收集发生时,系统首先把所有用户线程全部中断,如果发现有用户线程中断的地方不再安全点上,就恢复这条线程执行,让它一会再重新中断,直到到达安全点。

主动式中断(Voluntary Suspension):

在垃圾收集需要中断线程的时候,不直接对线程操作,仅简单的设置一个标志位,各个线程执行过程时会不停的主动去轮询这个标志,一旦发现中断标志为true时就在自己最近的安全点上主动挂起。

什么是安全区域?

安全点似乎解决了让虚拟机内部线程主动停顿,整个虚拟机进入垃圾回收状态的问题。但在实际情况下,如果线程处于sleep 或Blocked状态的话是没有分配CPU时间的,这时线程是无法响应虚拟机的中断请求,不能再走到安全点进行挂起,而虚拟机也不能持续的等待线程被重新激活分配CPU。这种情况,就必须引入安全区域(Safe Region)来解决问题了。

安全区域,可以看作是安全点的扩展。指的是能够确保在某一段代码片段中,引用关系不会发生变化,在这个区域中任意地方开始来及手机都是安全的。

安全区域内发生了什么?

当线程执行到安全区域里的代码时,会先标识自己进入了安全区域,如果这时段里进行了垃圾收集虚拟机就不必去管这些已经标识过的线程了

当线程离开安全区域时,它要检查下虚拟机是否完成了根节点的扫描或者垃圾收集过程中需要停顿的阶段。如果完成了,那线程就会继续执行。否则就必须一直等待,直到收到可以离开安全区域的信号。

结尾

看完这些,你能回答下面的问题吗!

垃圾收集器为什么必须要停顿下?

安全点和安全区域的区别?

往期推荐

每日一个知识点系列:volatile的可见性原理

(最新 9000字) Spring Boot 配置特性解析

何时用多线程?多线程需要加锁吗?线程数多少最合理?

Spring Boot 知识清单(一)SpringApplication

高并发系统,你需要知道的指标(RT...)

相关文章
|
6月前
|
算法 Java
如何减少垃圾回收停顿时间,以提高高性能应用程序的响应性
如何减少垃圾回收停顿时间,以提高高性能应用程序的响应性
|
3月前
|
算法 Java 开发者
G1垃圾回收器的停顿时间预测模型是如何工作的?
G1垃圾回收器的停顿时间预测模型是如何工作的?
|
缓存 算法 Java
透彻理解JVM中垃圾回收GC生产参数,停顿时间+执行效率相关参数
停顿时间相关参数 部分垃圾回收器实现了GC执行时应用最大停顿时间的功能,所以提供参数用于应用控制停顿时间。另外,GC为了满足停顿时间,会设计和实现一些动态算法来调整堆空间,从而满足停顿时间这个目标。本节介绍相关参数。 该参数表示GC的最大的停顿时间。不同GC对于该参数的行为不一致,具体来说: 1)若Parallel GC中GC执行的时间超过该值,将导致调整新生代和老生代的大小(参数UseAdaptiveSizePolicy设置为true)。参数的默认值为4294 967 295,大约为50天(所以通常不会触发这个调整策略)。 2)若G1中GC执行的时间超过该值,将导致调整新生代的大小和
|
1月前
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
63 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
|
2月前
|
监控 算法 Java
深入理解Java中的垃圾回收机制在Java编程中,垃圾回收(Garbage Collection, GC)是一个核心概念,它自动管理内存,帮助开发者避免内存泄漏和溢出问题。本文将探讨Java中的垃圾回收机制,包括其基本原理、不同类型的垃圾收集器以及如何调优垃圾回收性能。通过深入浅出的方式,让读者对Java的垃圾回收有一个全面的认识。
本文详细介绍了Java中的垃圾回收机制,从基本原理到不同类型垃圾收集器的工作原理,再到实际调优策略。通过通俗易懂的语言和条理清晰的解释,帮助读者更好地理解和应用Java的垃圾回收技术,从而编写出更高效、稳定的Java应用程序。
|
1月前
|
存储 Java PHP
【JVM】垃圾回收机制(GC)之引用计数和可达性分析
【JVM】垃圾回收机制(GC)之引用计数和可达性分析
60 0
|
2月前
|
监控 算法 Java
深入理解Java中的垃圾回收机制(GC)
本文将探讨Java的自动内存管理核心——垃圾回收机制。通过详细解析标记-清除算法、复制算法和标记-整理算法等常用垃圾回收算法,以及CMS、G1等常见垃圾回收器,帮助读者更好地理解Java应用的性能优化和内存管理。同时,探讨分代收集、分区收集等策略在实际项目中的应用。结语部分总结了垃圾回收机制在Java开发中的重要性,并展望了未来可能的发展。
54 0
|
3月前
|
缓存 监控 Java
"Java垃圾回收太耗时?阿里HBase GC优化秘籍大公开,让你的应用性能飙升90%!"
【8月更文挑战第17天】阿里巴巴在HBase实践中成功将Java垃圾回收(GC)时间降低90%。通过选用G1垃圾回收器、精细调整JVM参数(如设置堆大小、目标停顿时间等)、优化代码减少内存分配(如使用对象池和缓存),并利用监控工具分析GC行为,有效缓解了高并发大数据场景下的性能瓶颈,极大提升了系统运行效率。
75 4
|
3月前
|
算法 Java 应用服务中间件
探索JVM垃圾回收算法:选择适合你应用的最佳GC策略
探索JVM垃圾回收算法:选择适合你应用的最佳GC策略
|
4月前
|
监控 算法 Java
Java面试题:如何在Java中触发一次Full GC?请详细解释垃圾回收机制和知识
Java面试题:如何在Java中触发一次Full GC?请详细解释垃圾回收机制和知识
374 4