【译文】 GC 安全点 和安全区域
原文链接 : here
根引用 Root references
一个实例死了,意味着它变得无用。只用程序员知道一个实例是否已经无用。为了让程序知道一个实例是否已经无用,我们可以使用编译器分析,引用计数, 或者 可达性分析。
可达性分析假设只要一个实例是可达的,它就是活着的。如果一个实例的引用直接包含在当前函数栈的一个槽(slot)中,它就是直接可达的。那些被可达实例引用的实例也是可达的。因此,可达性分析就是找出那些直接可达的引用,也就是根引用。 根引用的集合就做根集合。
当前执行函数(the mutator)的上下文中 有直接可达的数据,因此 找根集合就是在上下文中找实例的引用。当前函数的上下文引用它的栈和寄存器文件(和一些线程所有的数据)。全局数据也是直接可达的。
枚举根集合Root set enumeration
一般情况下,如果GC使用可达性来确定一个实例是否存活,GC需要获得当前执行现场的一个一致的快照(a consistent snapshot),以便枚举根引用。 这对于stop-the-world 和 并发 GC(多数情况)都适用。 “一致” 意味着快照看起来就像在单个时间点上取得的。 一个一致的根引用快照对于正确性很有必要,否则一些活着的实例就可能丢失。 那现在的问题就是怎样获得当前上下文一致的快照。
为了获得一致的快照,一个简单的办法就是在枚举根引用的过程中,当前执行函数阻塞。 如果在枚举过程中,根集合是不变的,快照也是一致的。
当前执行函数阻塞了它的执行以后,它就不一定能够枚举它上下文中的根引用,除非它在它的上下文中登记并保存了那些引用信息。也就是说,它应该能够分辨出那个栈里有引用,哪个寄存器里有引用。 如果GC能够准确地获得这些信息,它就是准确根集合枚举, 否则就是模糊的。
(对应模糊枚举,GC使用启发式规则来保守地猜测哪些是上下文中的引用。因此,这些GC就是所谓的保守GC。 这篇文章只讨论准确枚举。)
Harmony 通过使用GC安全点和安全区域, 支持准确根集合枚举。
GC安全点和安全区域 Safe-point (or safepoint)
为了支持准确枚举,JIT编译器需要做一些额外的工作,因为只有JIT准确地知道栈帧信息和寄存器上下文。 当JIT编译一个方法的时候, 对于每一个指令, 它都保存根引用信息,以防执行阻塞在那个指令上。
但是对每一个指令都保存那些信息太昂贵了。 它需要大量空间保存那些信息。 这是不必要的,因为 只有一小部分指令有机会在实际执行时阻塞。 JIT只需要保存那部分指令的信息就够了-- 他们就把叫做安全点。安全点意味着对应根枚举来说,在该点阻塞是安全的。
顺便说一下,并不是所有编程语言的编译器都能够确切知道堆栈信息。 只有安全语言有这个能力。 比如, C/C++就没有。
函数阻塞 Mutator suspension
对于安全点,现在的问题是,我们怎么保证函数在安全点阻塞。
有两种基本方法来阻塞当前函数,抢先或者自愿。抢先式的方法是无论任何时候GC需要进行一次收集,它都立即阻塞当前函数的执行。当它发现函数被阻塞在一个不安全的点时,它会恢复函数执行,向前滚动到一个安全点。这种方法在ORP【1】中实现,它是Harmony的前一个版本。但是,目前几乎没有JVM使用这种方法。
在Harmony中实现的方法是自愿阻塞。当GC触发一次垃圾回收,它只是简单的设置一个标志; 当前执行函数会轮询这个标志, 当发现这个标志置位的时候,他们就会阻塞。那些轮询的点都是安全点。 多数情况下, JIT负责在合适的位置插入轮询程序。 有时,VM也需要有一些轮询点。
轮询点 Polling point
那么哪里是正确轮询GC触发事件的地点呢? 就像我们上面讨论的,我们不想在每一个指令处都设置轮询点。 对于自愿阻塞,一个更严重的问题是轮询负载。因此插入轮询点需要遵循一些基本原则:第一,轮询点应该足够频繁,以便GC不需要等待当前函数阻塞的时间太长, 因为其他函数还在等着GC释放空间来继续执行。第二,轮询点不能太多,导致增加运行负载过重。
最好的结果是刚好有足够的轮询点满足需求:
- 一类强制的轮询点是内存分配点。分配可以触发一次垃圾收集,因此分配必须是安全点
- 长时间的执行总是和方法调用或者循环 有关。因此,调用点和循环回边点也是期望的轮询点
这些就是Harmony中的轮询点: 分配点,调用点和循环回边点。 多数情况下运行时负载小于1%。 不幸的是,我们发现单独安全点是不够的。
安全区域 Safe-region
为什么不够呢? 因为我们忘掉了一种常见执行的情况。我们忘了它,因为它实际上不是长时间执行,而是长时间闲置。有这样一类情况程序不能及时响应GC触发事件,比如sleep,因系统调用阻塞。 这些操作不是JVM能够控制的。JVM在此期间不能够响应GC事件。 因此,我们引入了安全区域的概念来解决这个问题。
安全区域是其中引用不会改变的一段代码片段,那么在其中任一点进行根枚举都是安全的。 换句话说,安全区域是安全点的一个很大的扩展。
在安全点的设计中,如果GC触发事件发生了,执行函数通过轮询进行响应。它通过设置一个准备好的标志(ready flag)来响应。 那么GC就可以进行根枚举了。这是一个握手协议。
安全区域也遵循这个协议。执行函数在进入安全区域时设置ready flag。在它离开安全区域以前,它先检查GC是否完成了枚举(或者收集),并且不再需要执行函数呆在阻塞状态。如果是真的,它就向前执行,离开安全区域; 否则,它就像安全点一样阻塞他自己。
在Harmony的实现中,我们插入 suspend_enable 和 suspend_disable来标志安全区域的界限。
【1】 ORP (Open Runtime Platform), http://orp.sf.net ;
【译文】 GC 安全点 和安全区域的更多相关文章
- Java 内存区域和GC机制分析
目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 Java垃圾回收概况 Java GC(Garbage Collection, ...
- Java 内存区域和GC机制
目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 Java垃圾回收概况 Java GC(Garbage Collection, ...
- Java系列笔记(3) - Java 内存区域和GC机制
目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 Java垃圾回收概况 Java GC(Garbage Collection, ...
- 【转】Java之 内存区域和GC机制
转自:Leo Chin 目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 Java垃圾回收概况 Java GC(Garbage ...
- Java 内存区域和GC机制--备用
Java垃圾回收概况 Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之一,作为Java开发者,一般不需要专门编写内存回收和垃圾清理代 ...
- JAVA内存区域和GC机制
目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 Java垃圾回收概况 Java GC(Garbage Collection, ...
- Java内存区域和GC机制篇
Java内存区域和GC机制一.目录 1.Java垃圾回收概括 2.Java内存区域 3.Java对象的访问方式 4.Java内存访问机制 5.Java GC 机制 6.Java垃圾收集器 二.Java ...
- 【转载】Java系列笔记(3) - Java 内存区域和GC机制
Java系列笔记(3) - Java 内存区域和GC机制 转载:原文地址http://www.cnblogs.com/zhguang/p/3257367.html 目录 Java垃圾回收概况 Java ...
- 转载:Java 内存区域和GC机制
原文链接:http://www.cnblogs.com/hnrainll/archive/2013/11/06/3410042.html 目录 Java垃圾回收概况 Java内存区域 Java对象的访 ...
随机推荐
- HADOOP HA切换后出现MSSING BLOCK
HDFS HA切换后missing block问题分析 今天因为调整一个NN的参数,所以切换一个ACTIVE的NN,发生了MISSING BLOCK. 怀疑可能是EDITLOG没有同步完成,可能是误报 ...
- 虚基类&虚继承
发现这个月准备竞赛完全没有更新哎... 改了下某华大一c++测试题...网上对虚继承讲的要么太繁琐要么不到位,自力更生 #include<iostream> #include<fst ...
- 一段拼装sql的小代码
/** * 单表查询 * * className:实体类的名字 * vals:查询的属性 * pNames:条件的名字 * pVals:条件的值 */ @Override public List< ...
- [No000081]SVN学习笔记1-服务端搭建
目录 一:SVN服务器搭建和使用. 1.首先来下载和搭建SVN服务器,地址http://subversion.apache.org/packages.html 2.安装完成后,启动VisualSVN ...
- 第二天----列表、元组、字符串、算数运算、字典、while
列表 列表是最常用的Python数据类型,它可以作为一个方括号内的逗号分隔值出现. 基本操作: 索引切片追加删除长度切片循环包含 创建.查看列表: 列表中的数字不要加引号,列表的索引从0开始: lis ...
- Java 8简明教程
本文由 ImportNew 欢迎阅读我编写的Java 8介绍.本教程将带领你一步一步地认识这门语言的新特性.通过简单明了的代码示例,你将会学习到如何使用默认接口方法,Lambda表达式,方法引用和重复 ...
- SecureCRT连接虚拟机(ubuntu)配置
使用SecureCRT连接虚拟机(ubuntu)配置记录 这种配置方法,可以非常方便的操作虚拟机里的Linux系统,且让VMware在后台运行,因为有时候我直接在虚拟机里操作会稍微卡顿,或者切换速 ...
- Struts2:Json插件_Ajax
lib中加入包 struts2-json-plugin-2.3.20.jar json插件有自己的过滤器.返回类型 WebRoot下新建js文件夹 放入json2.js json2.js是一个著名开源 ...
- 搭建一套自己实用的.net架构(2)【日志模块-log4net】
先谈谈简单的模块,日志.在系统中日志模块是必须的,什么系统日志,操作日志,调试日志.这里用的是log4net. 对log4net还不熟悉的小伙伴们赶快去搜索基础教程哦, 我这里就不温故了. 那么有人要 ...
- 【原】python中文文本挖掘资料集合
这些网址是我在学习python中文文本挖掘时觉得比较好的网站,记录一下,后期也会不定期添加: 1.http://www.52nlp.cn/python-%E7%BD%91%E9%A1%B5%E7% ...