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

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

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

在垃圾收集器在获取根节点这一步时必须暂停用户线程的也就是我们常说的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...)

点赞
收藏
评论区
推荐文章
灯灯灯灯 灯灯灯灯
4年前
阿里面试被问到【垃圾回收器】,不会怎么办??
垃圾回收器GC分类与性能指标垃圾回收器概述1.垃圾收集器没有在规范中进行过多的规定,可以由不同的厂商、不同版本的JVM来实现。2.由于JDK的版本处于高速迭代过程中,因此Java发展至今已经衍生了众多的GC版本。3.从不同角度分析垃圾收集器,可以将GC分为不同的类型。Java不同版本新特性1.语法层面:Lambda表达式、switch、
从原理聊JVM(一):染色标记和垃圾回收算法
本篇介绍了JVM中垃圾回收器相关的基础知识,后续会深入介绍CMS、G1、ZGC等不同垃圾收集器的运作流程和原理,欢迎关注。
Wesley13 Wesley13
3年前
CMS垃圾回收过程
1.总体介绍:CMS(ConcurrentMarkSweep)是以牺牲吞吐量为代价来获得最短回收停顿时间的垃圾回收器。对于要求服务器响应速度的应用上,这种垃圾回收器非常适合。在启动JVM参数加上\XX:UseConcMarkSweepGC ,这个参数表示对于老年代的回收采用CMS。CMS采用的基础算法是:标记—清除。2.CMS
Stella981 Stella981
3年前
JVM系列篇:7种JVM垃圾收集器特点,优劣势、及使用场景
本系列会持续更新。!(https://oscimg.oschina.net/oscnet/945dbe48630eb4284fea936b19161c0f08a.jpg)今天继续JVM的垃圾回收器详解,如果说垃圾收集算法是JVM内存回收的方法论,那么垃圾收集器就是内存回收的具体实现。一、常见的垃圾收集器
Wesley13 Wesley13
3年前
Java G1 GC 垃圾回收深入浅出
1\.G1概览G1GC 全称是GarbageFirstGarbageCollector,垃圾优先垃圾回收器,以下简称G1。G1是HotSpotJVM的短停顿垃圾回收器。其实关于G1的论文早在2004年就有了,但是G1是在2012年4月发布的JDK7u4中才实现。从长期来说,G1旨在取代CMS(ConcurrentMark
Wesley13 Wesley13
3年前
Java人太南了!又要搞Spring,又要精通JVM垃圾回收和调优…
对象已死?啊,难受……最近深陷排查各种内存溢出、内存泄漏的问题,不得不对垃圾回收器下手了,因为当垃圾收集成为系统达到更高并发量的瓶颈时,我们就必须对这些“自动化”的技术实施必要的监控和调节。不少Java技术方向的兄弟,感觉也挺难的,常聊到各种高并发业务场景下,JVM涉及的性能问题、内存管理、垃圾回收器怎么弄?
Stella981 Stella981
3年前
JVM回收器与调优
定义:使用编程语言将GC算法实现出来,产生的程序就是垃圾搜集器了JVM给了三种选择:串行收集器、并行收集器、并发收集器串行搜集器(serialcollector):它只有一条GC线程,且就像前面说的,它在运行的时候需要暂停用户程序(stoptheworld)。并行搜集器(parallelcollector):它有多
Stella981 Stella981
3年前
JVM垃圾回收器思维导图
JVM垃圾回收器思维导图,介绍了各种垃圾回收器概述,垃圾收集的算法及其特点,使用场景!(https://oscimg.oschina.net/oscnet/2580cd2986314278b730349543a2bdbe.png)思维导图下载文件:(包含上次java线程)地址:https://pan.baidu.com/s/1nv
Stella981 Stella981
3年前
JVM架构体系与GC命令小总结
!(https://oscimg.oschina.net/oscnet/052a011b9ad19376d76daa6b6dcb82fa032.png)1.Overview2.JVM架构体系1)垃圾回收对象存活性判断垃圾回收算法垃圾回收器(回收算法的具体实现)
Stella981 Stella981
3年前
JVM03
前言今天来学习下与JVM垃圾收集机制相关的一些基本概念。如何判断对象是否存活垃圾收集器首要的任务的任务就是判断哪些对象是存活的,哪些对象已经死去了(这里死去的意思是对象不再被任何途径使用)。引用计数算法引用计数算法是在对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加一;当引用失效时,计数器
Stella981 Stella981
3年前
JVM的GC算法总结
Java程序在运行过程中,会产生大量的内存垃圾(一些没有引用指向的内存对象都属于内存垃圾,因为这些对象已经失去标记,程序用不了它们了,对程序而言它们已经废弃),为了确保程序运行时的性能,java虚拟机在程序运行的过程中不断地进行自动的垃圾回收(GC),这就是我们的垃圾回收机制,关于垃圾回收我总结了一下几种:标记–清除算法(MarkSweep)