jvm gc,gc算法
如前一篇文章中所述,HotSpot JVM中有四个可用的垃圾收集器。 它们之间有一些显着差异,但是用于完成实际工作的算法背后的实际概念非常相似。 在这篇简短的文章中,我将尝试解释三种基本算法:
- 打标
- 打标紧凑
- 标记复制
GC根
在进入细节之前,请确保我们对什么是GC根有一个共识。 这些是可以从堆外部直接访问的对象。 例如:
- 活动线程
- 静态变量
- 局部变量(可通过线程堆栈访问)
- JNI参考
标记
讨论的所有算法都具有相同的标记阶段。 标记阶段是从GC根开始遍历整个对象图。 当GC访问该对象时,它将其标记为可访问并因此处于活动状态。 从GC根无法访问的所有对象都是垃圾。 标记需要暂停(STW)暂停,因为正在运行的应用程序线程可能会干扰。 STW暂停的时间长短主要取决于访问对象的数量。
打标
在标记阶段之后,我们拥有了已访问(可通过GC根访问)和未访问对象占用的内存空间。 扫描阶段将释放包含无法访问对象的内存片段。 这很简单,但是由于死对象不一定彼此相邻,因此最终导致内存碎片化。 这本身还不错,但是尝试将太大的对象放入内存中可能导致OutOfMemoryError 。
打标紧凑
该算法解决了内存碎片的问题。 标记所有活动对象后,它们将移到内存空间的开头。 这有助于避免由于内存碎片过多而导致的OutOfMemoryError ,但是压缩堆并不是免费的。 复制对象和更新对它们的所有引用都需要时间,并且所有操作都在STW暂停期间发生。
标记复制
标记复制算法将所有活动对象复制到新的内存区域。 先前占用的区域被认为是空闲的。 下次执行标记复制时,所有活动对象都移回到上一个存储区。 您可以想象,这当然会导致内存压缩。 不幸的是,它需要额外的额外区域,该区域必须足够大以适合任何给定时间点的所有活动对象。
翻译自: https://www.javacodegeeks.com/2017/09/gc-explained-algorithms.html
jvm gc,gc算法