我正在尝试更深入地了解Java的垃圾收集。
在HotSpot JVM分代收集中,堆中分为三个区域(年轻代、老年代和永久代)。另外,还有两种算法:
1) 标记扫描紧凑型.
2) 并发标记和清除.
GC 是否需要“Stop-the-world”取决于它使用的算法而不是它运行在哪一代上,这是真的吗?换句话说,如果我在所有三个区域上使用 1) 作为 GC 算法,STW 总会发生吗?
另外,我理解的区别是第二个 GC 算法不需要压缩,这最终会导致碎片。那么第二个问题就来了,为什么compaction需要STW暂停?
压缩导致 STW 暂停的关键原因如下,JVM 需要移动对象并更新对其的引用。现在,如果您在更新引用之前移动对象,并且正在运行的应用程序从旧引用访问它,则会出现麻烦。如果您先更新引用然后尝试移动对象,则更新的引用是错误的,直到对象被移动为止,并且对象未移动时的任何访问都会导致问题。
对于 CMS 和并行收集器,年轻代收集算法是相似的,并且它是停止世界,即在收集发生时应用程序停止
JVM 正在做的事情是,标记从根集可访问的所有对象,将对象从 Eden 移动到幸存者空间,并将在超出保留阈值的集合中幸存下来的对象移动到老年代。当然,JVM 必须更新所有已移动对象的引用。
对于老一代并行收集器来说,所有标记、压缩和引用更新都在一个停止世界 (STW) 阶段进行,这会导致 GB 堆在几秒钟内暂停。这对于具有严格响应时间要求的应用程序来说是痛苦的。到目前为止,并行收集器仍然是吞吐量或批处理方面最好的收集器(在 Oracle Java 中)。事实上,我们已经看到,对于相同的场景,即使并行收集器花费的时间比 CMS 更多,我们仍然可以获得更高的吞吐量,我认为这与由于压缩而产生的更好的空间局部性有关。
CMS 通过并发标记解决了主收集中高暂停的问题。 STW 有 2 个部分:初始标记(从根集中获取引用)和重新标记暂停(标记结束时短暂的 STW 暂停,以在标记和应用程序同时工作时处理对象图中的更改)。对于几 GB 的堆大小和合理数量的应用程序线程,这两种暂停的范围都是 100 -200 毫秒(请记住,活动线程越多,根就越多)
G1GC 计划取代 CMS 并接受暂停目标。通过增量压缩堆来处理碎片。虽然工作是增量的,所以您可以获得更小的暂停,但这可能会以更频繁的暂停为代价
当应用程序运行时,以上都不能压缩堆(CMS根本不压缩)。 AZUL GPGC 垃圾收集甚至可以在不停止应用程序的情况下进行压缩,并且还可以处理引用更新。因此,如果您想深入了解 GC 的工作原理,那么值得阅读 GPGC 的算法。 AZUL 将其定位为无暂停收集器。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)