Excel不相邻列如何打印在一起-英雄云拓展知识分享
100
2023-11-07
【摘要】 本书摘自《深入理解 Java 虚拟机 JVM 高级特性与最佳实践(第3版)》一书中第3章,第4节,周志明著。
3.4.2 安全点
在OopMap 的协助下,HotSpot 可以快速准确地完成GC Roots 枚举,但一个很现实的 问题随之而来:可能导致引用关系变化,或者说导致 OopMap 内容变化的指令非常多,如 果为每一条指令都生成对应的OopMap, 那将会需要大量的额外存储空间,这样垃圾收集 伴随而来的空间成本就会变得无法忍受的高昂。
实际上 HotSpot 也的确没有为每条指令都生成OopMap, 前面已经提到,只是在“特定 的位置”记录了这些信息,这些位置被称为安全点 (Safepoint) 。 有了安全点的设定,也就 决定了用户程序执行时并非在代码指令流的任意位置都能够停顿下来开始垃圾收集,而是 强制要求必须执行到达安全点后才能够暂停。因此,安全点的选定既不能太少以至于让收 集器等待时间过长,也不能太过频繁以至于过分增大运行时的内存负荷。安全点位置的选 取基本上是以“是否具有让程序长时间执行的特征”为标准进行选定的,因为每条指令执 行的时间都非常短暂,程序不太可能因为指令流长度太长这样的原因而长时间执行,“长时 间执行”的最明显特征就是指令序列的复用,例如方法调用、循环跳转、异常跳转等都属 于指令序列复用,所以只有具有这些功能的指令才会产生安全点。
对于安全点,另外一个需要考虑的问题是,如何在垃圾收集发生时让所有线程(这里其 实不包括执行JNI 调用的线程)都跑到最近的安全点,然后停顿下来。这里有两种方案可供 选择:抢先式中断 (Preemptive Suspension) 和主动式中断 (Voluntary Suspension),抢先式
中断不需要线程的执行代码主动去配合,在垃圾收集发生时,系统首先把所有用户线程全 部中断,如果发现有用户线程中断的地方不在安全点上,就恢复这条线程执行,让它一会 再重新中断,直到跑到安全点上。现在几乎没有虚拟机实现采用抢先式中断来暂停线程响 应GC 事件。
而主动式中断的思想是当垃圾收集需要中断线程的时候,不直接对线程操作,仅仅简 单地设置一个标志位,各个线程执行过程时会不停地主动去轮询这个标志, 一旦发现中断 标志为真时就自己在最近的安全点上主动中断挂起。轮询标志的地方和安全点是重合的, 另外还要加上所有创建对象和其他需要在Java 堆上分配内存的地方,这是为了检查是否即 将要发生垃圾收集,避免没有足够内存分配新对象。
由于轮询操作在代码中会频繁出现,这要求它必须足够高效。HotSpot使用内存保护陷 阱的方式,把轮询操作精简至只有一条汇编指令的程度。下面代码清单3-4中的 test 指令就 是HotSpot 生成的轮询指令,当需要暂停用户线程时,虚拟机把0x160100 的内存页设置为 不可读,那线程执行到test 指令时就会产生一个自陷异常信号,然后在预先注册的异常处 理器中挂起线程实现等待,这样仅通过一条汇编指令便完成安全点轮询和触发线程中断了。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们 18664393530@aliyun.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~