上篇文章中,我们了解了Java虚拟机垃圾回收的思路和策略,这篇文章我们将了解Java是如何实现高效的回收算法的。

  我们需要了解,内存回收必须要保证“一致性”,意思就是在执行GC分析的时候,系统看起来要像是冻结在某一时间点上,不能出现在分析过程中,引用的情况还在发生变化,这样就无法进行分析,这是为什么在GC时必须要停顿所有的Java线程(官方称之为Stop The World),Java是通过引用计数器和可达性分析算法来判断一个对象是否可以被回收的,在进行可达性分析的时候,首先要枚举出所有的根结点GC-Roots,一个一个去挑选显然是不现实的,因为这会导致系统长时间的STW,而且,虚拟机是可以知道哪些地方存在存放着直接引用的,依靠使用一种叫做OOP的数据结构来达到这个目的,在类加载完成的时候,HotSpot就把对象内什么偏移量上是什么类型的数据计算出来,在JIT编译的过程中,也会在特定的位置几下栈和寄存器中哪些位置是引用,这样在GC扫描时,就可以直接获取这些信息了。

  上文也提到,并不会为每一条指令都创建OOP,因为这样会产生大量的内存消耗,得不偿失只会在特定位置创建,这个位置就是“安全点(Safe Point)”,程序只有在安全点才可以停下来执行GC,安全点设置的时候,为了追求合理(例如当需要执行GC时,不能让GC等候太久才进入安全点),这个标准就是“是否会让程序执行太久”,注意,这个判断条件不能以指令集的长度来判断,因为每条指令执行的时间都很短,其最明显的特征就是指令序列复用,例如方法跳转,循环跳转,异常跳转等,所以,具有这些功能的指令才会产生安全点。

  对于安全点,另一个需要考虑的问题是如何在GC发生时,让所有的线程都跑到最近的安全点上停下来,这里有两个方案选择:一是抢先式中断,就是在GC发生时,将所有的线程中断,如果发现有线程中断的地方不在安全点上,就恢复该线程,现在几乎没有虚拟机采用这种抢先式中断;而是主动式中断,设置一个标志,在GC发生时,该标志为真,在每个安全点上去查看这个标志,当这个标志为真时,就自己挂起中断。

  另外我们需要扩充一个安全域的概念,因为当有些线程正好处于Sleep或Block状态时,无法响应JVM的暂停请求,JVM也不可能等待CPU重新分配时间片,这就需要安全域来解决,安全域是指在一个代码片段中,引用关系不会发生变化,在这个区域中任何地方开始GC都是安全的,我们可以把安全域看作是对安全点的一个扩充。当线程执行到Safe Region时,就会标识自己已经进入SafeRegion,当需要执行GC时,不用管这种线程,当这种线程将要跳出SafeRegion时,会检查系统是否已经枚举完了根结点(或整个GC过程完成),如果没有,则必须等待到可以安全离开SafeRegion的信号为止。

  可以看出,JVM在具体的实现细节上遇到了很多问题,所以我们要深入了解JVM,学习优秀的解决方案,不能只停留在表面。

  本文我们了解了JVM在执行GC时的一些细节,下篇文章我们将会介绍几种流行的商用垃圾收集器。

深入理解JVM(六) -- GC执行原则和方案的更多相关文章

  1. 深入理解JVM+G1+GC.pdf (中文版带书签)

    目录 序 VII前言 IX 第1章 JVM & GC基础知识 11.1 引言 21.2 基本术语 31.2.1 Java相关术语 41.2.2 JVM/GC通用术语 241.2.3 G1涉及术 ...

  2. 深入理解JVM—字节码执行引擎

    原文地址:http://yhjhappy234.blog.163.com/blog/static/3163283220122204355694/ 前面我们不止一次的提到,Java是一种跨平台的语言,为 ...

  3. 深入理解JVM与GC回收

    JVM内存模型 java虚拟机在执行java程序的过程中会把它所管理的内存划分为不同的若干个不同的的数据区域,这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机的进程的启动而存在,有些区 ...

  4. 深入理解JVM(六)类文件结构

    6.1 关于类文件 1.class文件的一次编译,到处运行的跨平台性: 2.JVM不止有跨平台性,还有跨语言性,不管是JRuby还是Groovy写出来的程序,只要编译出符合JVM规范的class文件就 ...

  5. 深入理解JVM——虚拟机GC

    对象是否存活 Java的GC基于可达性分析算法(Python用引用计数法),通过可达性分析来判定对象是否存活.这个算法的基本思想是通过一系列"GC Roots"的对象作为起始点,从 ...

  6. Java 中级 学习笔记 1 JVM的理解以及新生代GC处理流程

    写在最前 从毕业到现在已经过去了差不多一年的时间,工作还算顺利,但总是离不开CRUD ,我觉得这样下去肯定是不行的,温水煮青蛙,势必有一天,会昏昏沉沉的迷失在温水里.所以,需要将之前学习JAVA 当中 ...

  7. 理解JVM GC

    理解JVM GC对于我们把控Java应用有很大的帮助.下面我从运维角度,把网上的JVM相关的资料整理如下,以加深对JVM GC的理解.如有错误的地方,请看官指正. JVM内存使用分类 JVM的内存分区 ...

  8. 深入理解JVM - 虚拟机字节码执行引 - 第八章

    概述从外观上看起来,所有的 Java 虚拟机的执行引擎都是一致的:输入的是字节码文件,处理过程是字节码解析的等效过程,输出的是执行结果.主要从概念模型的角度来讲解虚拟机的方法调用和字节码执行. 运行时 ...

  9. jvm入门及理解(六)——垃圾回收与算法

    一.jvm垃圾回收要做的事情 哪些内存需要回收 什么时候回收 怎么回收 二.如何判断对象已经死亡,或者说确定为垃圾 引用计数法: 给对象中添加一个引用计数器,每当有一个地方引用它时,计数器的值就加1: ...

随机推荐

  1. Codeforces 839D Winter is here - 暴力 - 容斥原理

    Winter is here at the North and the White Walkers are close. John Snow has an army consisting of n s ...

  2. python 运行当前目录下的所有文件

     查看当前目录下所有py文件(本身除外run) import os file_list = os.listdir(os.getcwd()) # 获取当前目录下所有的文件名print(file_list ...

  3. 京津冀大学生竞赛:babyphp

    京津冀大学生竞赛:babyphp 比赛的时候没做出来,回来以后一会就做出来了,难受...还是基本功不扎实,都不记得__invoke怎么触发的了 放上源码 <?php error_reportin ...

  4. PhpStorm 头部注释、类注释和函数注释的设置(稍微完善点)

    首先,PhpStorm中文件.类.函数等注释的设置在:setting->Editor->FIle and Code Template->Includes下设置即可,其中方法的默认是这 ...

  5. protobuf使用

    一.protobuf环境搭建 Github 地址: https://github.com/protocolbuffers/protobuf 然后进入下载页 https://github.com/pro ...

  6. Python中为什么没有++和–(自增/减)(转)

    原文地址:http://blog.csdn.net/guang09080908/article/details/47273775(侵删) 这两天看了一些网上各大互联网公司的面试题,发现腾讯特别喜欢考察 ...

  7. CSS MDN - 选择器与样式化文字

  8. 解决electron-vue中无法Element的Tooltip组件

    打开文件:electron-vue/webpack.renderer.config.js 在大约21行左右找到 let whiteListedModules 将element-ui添加进去,最终如下所 ...

  9. git pull push 所有分支

    因为远端 git 服务器上有很多分支,一个个分支pull太麻烦,所以找了 pull 所有分支的方法,如下: git branch -r | grep -v '\->' | while read ...

  10. Qt QtXml读取xml文件内容

    Qt QtXml读取xml文件内容 xml文件内容 <?xml version="1.0" encoding="UTF-8"?> <YG_RT ...