石家庄手机网站建设,网页设计技巧,网站建设与知识产权,wordpress 空间不足作为使用范围最广的虚拟机之一HotSpot#xff0c;必须对垃圾回收算法的执行效率有严格的考量#xff0c;只有这样才能保证虚拟机高效运行 枚举根节点 从可达性分析中从 GC Roots 节点找引用链这个操作为例#xff0c;可以作为 GC Roots 的节点主要在全局性的引用#xff08… 作为使用范围最广的虚拟机之一HotSpot必须对垃圾回收算法的执行效率有严格的考量只有这样才能保证虚拟机高效运行 枚举根节点 从可达性分析中从 GC Roots 节点找引用链这个操作为例可以作为 GC Roots 的节点主要在全局性的引用例如常量或者类静态属性与执行上下文例如栈帧中的本地变量表中。 但是现在很多应用仅仅方法区就有数百兆如果要逐个检查这里面的引用那么必然会消耗很多的时间。 另外可达性分析对执行时间的敏感还体现在 GC 停顿上因为这项分析工作必须在一个能确保一致性的快照中进行 —— 这里的“一致性”指的是在整个分析过程中整个执行系统看起来就像是被冻结在某个时间点上不可以出现分析过程中对象引用关系还在不停变化的情况该点不满足的话分析结果准确性就无法得到保证。 这点是导致 GC 进行时必须停顿所有 Java 执行线程的其中一个重要原因即使是号称不会发生停顿的 CMS 收集器中枚举根节点也是必须要停顿的。 由于目前主流 Java 虚拟机使用的都是准确式 GC所以当执行系统停顿下来后并不需要一个不漏的检查完成所有执行上下文和全局的引用位置虚拟机应当是有办法直接得知那些地方存放着对象引用的。 在HotSpot的实现中是使用一组被称为OopMap的数据结构来达到这个目的的在类加载的时候HotSpot就把对象内什么偏移量上是什么类型的数据计算出来在JIT 编译过程中也会在特定的位置记录下栈和寄存器中哪些位置是引用。这样 GC 在扫描时就可以直接得知这些信息了。 安全点 在 OopMap 的帮助下HotSpot 可以快速并且准确的完成 GC Roots 枚举但是一个很现实的问题随之而来可能导致引用关系变化或者说 OopMap 内容变化的指令非常多如果为每一条指令都生成对应的 OopMap那么将需要大量的额外空间这样 GC 的空间成本将会变得很高。 实际上HotSpot 也的确没有为每一条指令都生成 OopMap只是在“特定的位置” 记录了这些信息这些位置被称为是安全点即程序执行时并非是在所有地方都能停顿下来开始 GC 只有到达安全点时才能暂停。 安全点的选择既不能太少以至于让 GC 等待太长时间也不能过于频繁以至于过分增大运行时负荷。 所以安全点的选定基本上是以程序“是否具有让程序长时间执行的特征”为标准进行选定的——因为每条指令执行的时间都非常短暂程序不太可能因为指令流长度太长这个原因而过长时间运行“长时间执行”的最明显特征就是指令序列复用例如方法调用、循环跳转、异常跳转等所以具有这些功能的指令才会产生安全点。 对于安全点另一个需要考虑的问题就是如何让 GC 发生时让所有线程这里不包括执行 JNI 调用的线程都“跑”到最近的安全点再停顿下来。这里有两种方案可供选择抢先式中断和主动式中断。 抢先式中断无需线程的执行代码主动配合在 GC 发生时首先把所有线程全部中断如果发现有线程中断的地方不再安全点上就会发线程让它“跑”到安全点上。现在几乎没有虚拟机实现采用抢先式中断来暂停线程从而响应GC事件主动式中断当 GC 需要中断线程时不直接对线程操作仅仅简单地设置一个标志各个线程执行时主动去轮询这个标志发现中断标志为真时就自己中断挂起。轮询标志的地方和安全点是重合的另外再加上创建对象需要分配内存的地方。安全区域 使用安全点似乎已经完美解决了如何进入 GC 的问题但实际情况却并不一定安全点机制保证了程序执行在不太长的时间内就会遇到可以进入 GC 的安全点。 但是线程“不执行”的时候呢所谓不执行就是没有分配 CPU 时间典型的例子就是线程处于 Sleep 状态或者 Blocked状态这时候线程无法响应 JVM 的中断请求“走”到安全点去中断挂起JVM显然也不太可能等待线程重新被分配 CPU 时间。对于这种状况就需要安全区域来解决。 安全区域就是在一段代码片段中引用关系不会发生变化在这个区域中的任意地方开始 GC 都是安全的。 在线程执行到安全区域中的代码时首先标识自己已经进入了安全区域那样当这段时间里 JVM 要发起 GC 时就不用管标识自己为安全区域状态的线程了。 当线程要离开安全区域时它要检查系统是否已经完成了根节点枚举或者是整个 GC 过程如果完成了那线程就继续执行否则它就必须等待直到收到可以安全离开安全区域的信号为止。 转载于:https://www.cnblogs.com/AmosH/p/10346924.html