原文链接 : 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释放空间来继续执行。第二,轮询点不能太多,导致增加运行负载过重。

  最好的结果是刚好有足够的轮询点满足需求:

  1. 一类强制的轮询点是内存分配点。分配可以触发一次垃圾收集,因此分配必须是安全点
  2. 长时间的执行总是和方法调用或者循环 有关。因此,调用点和循环回边点也是期望的轮询点  

  这些就是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 安全点 和安全区域的更多相关文章

  1. Java 内存区域和GC机制分析

    目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 Java垃圾回收概况 Java GC(Garbage Collection, ...

  2. Java 内存区域和GC机制

    目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 Java垃圾回收概况 Java GC(Garbage Collection, ...

  3. Java系列笔记(3) - Java 内存区域和GC机制

    目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 Java垃圾回收概况 Java GC(Garbage Collection, ...

  4. 【转】Java之 内存区域和GC机制

    转自:Leo Chin 目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 Java垃圾回收概况 Java GC(Garbage ...

  5. Java 内存区域和GC机制--备用

    Java垃圾回收概况 Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之一,作为Java开发者,一般不需要专门编写内存回收和垃圾清理代 ...

  6. JAVA内存区域和GC机制

    目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 Java垃圾回收概况 Java GC(Garbage Collection, ...

  7. Java内存区域和GC机制篇

    Java内存区域和GC机制一.目录 1.Java垃圾回收概括 2.Java内存区域 3.Java对象的访问方式 4.Java内存访问机制 5.Java GC 机制 6.Java垃圾收集器 二.Java ...

  8. 【转载】Java系列笔记(3) - Java 内存区域和GC机制

    Java系列笔记(3) - Java 内存区域和GC机制 转载:原文地址http://www.cnblogs.com/zhguang/p/3257367.html 目录 Java垃圾回收概况 Java ...

  9. 转载:Java 内存区域和GC机制

    原文链接:http://www.cnblogs.com/hnrainll/archive/2013/11/06/3410042.html 目录 Java垃圾回收概况 Java内存区域 Java对象的访 ...

随机推荐

  1. HADOOP HA切换后出现MSSING BLOCK

    HDFS HA切换后missing block问题分析 今天因为调整一个NN的参数,所以切换一个ACTIVE的NN,发生了MISSING BLOCK. 怀疑可能是EDITLOG没有同步完成,可能是误报 ...

  2. 虚基类&虚继承

    发现这个月准备竞赛完全没有更新哎... 改了下某华大一c++测试题...网上对虚继承讲的要么太繁琐要么不到位,自力更生 #include<iostream> #include<fst ...

  3. 一段拼装sql的小代码

    /** * 单表查询 * * className:实体类的名字 * vals:查询的属性 * pNames:条件的名字 * pVals:条件的值 */ @Override public List< ...

  4. [No000081]SVN学习笔记1-服务端搭建

    目录 一:SVN服务器搭建和使用. 1.首先来下载和搭建SVN服务器,地址http://subversion.apache.org/packages.html 2.安装完成后,启动VisualSVN ...

  5. 第二天----列表、元组、字符串、算数运算、字典、while

    列表 列表是最常用的Python数据类型,它可以作为一个方括号内的逗号分隔值出现. 基本操作: 索引切片追加删除长度切片循环包含 创建.查看列表: 列表中的数字不要加引号,列表的索引从0开始: lis ...

  6. Java 8简明教程

    本文由 ImportNew 欢迎阅读我编写的Java 8介绍.本教程将带领你一步一步地认识这门语言的新特性.通过简单明了的代码示例,你将会学习到如何使用默认接口方法,Lambda表达式,方法引用和重复 ...

  7. SecureCRT连接虚拟机(ubuntu)配置

    使用SecureCRT连接虚拟机(ubuntu)配置记录   这种配置方法,可以非常方便的操作虚拟机里的Linux系统,且让VMware在后台运行,因为有时候我直接在虚拟机里操作会稍微卡顿,或者切换速 ...

  8. Struts2:Json插件_Ajax

    lib中加入包 struts2-json-plugin-2.3.20.jar json插件有自己的过滤器.返回类型 WebRoot下新建js文件夹 放入json2.js json2.js是一个著名开源 ...

  9. 搭建一套自己实用的.net架构(2)【日志模块-log4net】

    先谈谈简单的模块,日志.在系统中日志模块是必须的,什么系统日志,操作日志,调试日志.这里用的是log4net. 对log4net还不熟悉的小伙伴们赶快去搜索基础教程哦, 我这里就不温故了. 那么有人要 ...

  10. 【原】python中文文本挖掘资料集合

    这些网址是我在学习python中文文本挖掘时觉得比较好的网站,记录一下,后期也会不定期添加:   1.http://www.52nlp.cn/python-%E7%BD%91%E9%A1%B5%E7% ...