JVM垃圾回收算法实现的方式

简介: 通过前面的介绍我们清楚了JVM中对象是如何判断存活及垃圾回收算法。那么垃圾回收的算法到底是怎么实现的呢?因为HotSpot虚拟机在对对象回收的时候对执行的效率要求是非常严格的,只有这样才能保证虚拟机的高效运行。


 通过前面的介绍我们清楚了JVM中对象是如何判断存活及垃圾回收算法。那么垃圾回收的算法到底是怎么实现的呢?因为HotSpot虚拟机在对对象回收的时候对执行的效率要求是非常严格的,只有这样才能保证虚拟机的高效运行。

垃圾收集算法

枚举根节点

 我们知道可达性分析算法是需要GC Roots对象的,而GR Roots对象的组成是这四种。

序号 类型

1 虚拟机栈(本地变量表)中引用的对象

2 方法区中类静态属性引用的对象

3 方法区中常量引用的对象

4 本地方法栈中JNI(一般说的Native方法)引用的对象

image.png  上图是简单的将GC Roots对象的组成简单的描述了下。清楚了这个之后我们再回到垃圾回收的问题,在很多应用中仅仅方法区就有几百MB,那么如果一个一个检查引用,那么将会非常的消耗时间。而且因为在枚举GC Roots节点时,程序时需要停顿的【Stop The World】(不可以出现分析过程中对象引用关系还在不断变化的情况,这是保证分析结果准确性的基础。)所以我们不可能花费大量的时间去扫描方法区,那么虚拟机是如何实现在不扫描方法区的情况下找到可作为GC Roots的对象呢?

 在HotSpot的实现中,是使用一组称为OopMap的数据结构来达到这个目的的,在类加载完成的时候,HotSpot就把对象内什么偏移量上是什么类型的数据计算出来,在JIT编译(即时编译器)过程中,也会在特定的位置记录下栈和寄存器中哪些位置是引用。这样,GC在扫描时就可以直接从OopMap中获取到GC Roots的对象。而不用一个一个去查找了。(以空间换时间)

安全点

 我们现在已经知道了在OopMap的帮助下我们可以快速的完成GC Roots的枚举,那么这就会出现一个问题:可能导致引用关系变化,或者说OopMap内容变化的指令非常多,如果为每一条指令都生成对应的OopMap,那将会需要大量的额外空间,这样GC的空间成本将会变得很高。那么虚拟机是如何解决这个问题的呢?

 实际上HotSpot也没有为每条指令都生成OopMap,而是只在“特定的位置”记录这些信息,这些位置便被称为安全点(Safepoint)。也就是说,程序执行时并非在所有地方都能停顿下来开始GC,只有在到达安全点时才能暂停。Safepoint的选定既不能太少以致于让GC等待时间太长,也不能过于频繁以致于过分增大运行时的负荷。所以,安全点的选定基本上是以程序是否具有让程序长时间执行的特征为标准进行选定的——因为每条指令执行的时间都非常短暂,程序不太可能因为指令流长度太长这个原因而过长时间运行,长时间执行的最明显特征就是指令序列复用,例如方法调用、循环跳转、异常跳转等,所以具有这些功能的指令才会产生Safepoint。

 对于Sefepoint,另一个需要考虑的问题是如何在GC发生时让所有线程(这里不包括执行JNI调用的线程)都“跑”到最近的安全点上再停顿下来。这里有两种方案可供选择:

image.png

安全区

 Safepoint机制保证了程序执行时,在不太长的时间内就会遇到可进入GC的Safepoint。但是,程序“不执行”的时候(如线程处于Sleep状态或Blocked状态),这时线程无法响应JVM的中断请求,“走到”安全的地方去中断挂起,这时候就需要安全区域(Safe Region)来解决。

 安全区域是指在一段代码片段之中,引用关系不会发生变化。在这个区域中的任意地方开始GC都是安全的。我们也可以把Safe Region看做是被扩展了的Safepoint。

 在线程执行到Safe Region中的代码时,首先标识自己已经进入了Safe Region,那样,当在这段时间里JVM要发起GC时,就不用管标识自己为Safe Region状态的线程了。在线程要离开Safe Region时,它要检查系统是否已经完成了根节点枚举(或者是整个GC过程),如果完成了,那线程就继续执行,否则它就必须等待直到收到可以安全离开Safe Region的信号为止。

参考《深入理解Java虚拟机》


相关文章
|
22天前
|
算法 Java
JVM垃圾回收机制
JVM垃圾回收机制
15 0
|
1月前
|
Java 程序员
探讨JVM垃圾回收机制与内存泄漏
探讨JVM垃圾回收机制与内存泄漏
|
2月前
|
算法 Java 关系型数据库
掌握这3个技巧,你也可以秒懂JAVA性能调优和jvm垃圾回收
JVM 是一个虚拟化的操作系统,类似于 Linux 和 Window,只是他被架构在了操作系统上进行接收 class 文件并把 class 翻译成系统识别的机器码进行执行,即 JVM 为我们屏蔽了不同操作系统在底层硬件和操作指令的不同。
24 0
|
2月前
|
存储 缓存 算法
JVM的垃圾回收机制
JVM的垃圾回收机制
|
3月前
|
算法 Java
JVM GC和常见垃圾回收算法
JVM GC和常见垃圾回收算法
48 0
|
12天前
|
存储 前端开发 安全
JVM内部世界(内存划分,类加载,垃圾回收)(上)
JVM内部世界(内存划分,类加载,垃圾回收)
46 0
|
16天前
|
存储 缓存 算法
深度解析JVM世界:垃圾判断和垃圾回收算法
深度解析JVM世界:垃圾判断和垃圾回收算法
|
1月前
|
Java Serverless 对象存储
Serverless 应用引擎常见问题之jvm在进行垃圾回收的时候会导致重启如何解决
Serverless 应用引擎(Serverless Application Engine, SAE)是一种完全托管的应用平台,它允许开发者无需管理服务器即可构建和部署应用。以下是Serverless 应用引擎使用过程中的一些常见问题及其答案的汇总:
22 0
|
1月前
|
算法 Java UED
【JVM】分代收集算法:提升Java垃圾回收效率
【JVM】分代收集算法:提升Java垃圾回收效率
21 0
|
1月前
|
算法 Java
深入了解JVM和垃圾回收算法
深入了解JVM和垃圾回收算法
24 0