回想一下 Java 中的垃圾回收是什么
垃圾收集是通过销毁未使用的对象来回收完整的运行时内存的过程。
有时程序员可能会忘记销毁无用的对象,而分配给它们的内存并没有被释放。越来越多的系统内存被消耗,最终不再分配。此类应用程序遭受“内存泄漏”。
在某个点之后,不再有足够的内存来创建新对象,并且程序由于OutOfMemoryError异常终止。
Java 中的垃圾收集是 Java 程序自动管理内存的过程。Java 程序被编译成在 Java 虚拟机 (JVM) 上运行的字节码。
当 Java 程序在 JVM 上运行时,对象是在堆上创建的,堆是分配给它们的内存部分。
当 Java 应用程序运行时,会在其中创建新对象。最后,一些对象不再需要了。我们可以说,在任何给定时间,堆内存都由两种类型的对象组成。
- Live - 这些对象被使用,它们是从其他地方引用的。
- 已死- 这些对象未在其他任何地方使用,没有对它们的引用。
垃圾收集器找到这些未使用的对象并将它们移除以释放内存。
Java 中的垃圾收集是一个自动过程。程序员不需要明确标记要删除的对象。
每个 JVM 都可以实现自己的垃圾收集版本。但是,收集器必须符合标准 JVM 规范来处理堆内存中存在的对象,以标记或识别无法访问的对象并通过压缩销毁它们。
对象可达性
为了将一个对象识别为活着的,仅存在链接是不够的。这是因为一些死对象可以引用其他死对象。这就是为什么在对一个对象的所有引用中,至少应该有一个来自“活动”对象的引用是必要的。
垃圾收集器使用 GC Roots(垃圾收集根)的概念来区分活对象和死对象。有 100% 的活动对象,从它们中有链接可以使其他对象动画化等等。
此类根的示例:
- 由系统类加载器加载的类。
- 现场直播。
- 当前正在执行的方法和局部变量的参数。
- 用作同步监视器的对象。
- 出于某种目的从垃圾回收中保留的对象。
- 垃圾收集器遍历内存中的整个对象图,从这些根开始,然后跟随对其他对象的引用。
Java中的垃圾收集步骤
标准的垃圾回收实现分为三个步骤。
1. 将对象标记为活动的
此时,垃圾收集器 (GC) 必须通过遍历对象图来识别内存中的所有存活对象。
当它访问一个对象时,它会将其标记为可用并因此处于活动状态。所有不能从 GC 根访问的对象都被认为是垃圾收集的候选对象。
2.清理死物
在标记阶段之后,内存空间被活的(访问过的)或死的(未访问过的)对象占用。清理阶段释放包含这些死对象的内存碎片。
3.内存中剩余对象的紧凑排列
上一阶段移除的死对象不必彼此相邻。因此,您冒着获得碎片化(半空)内存空间的风险。
但是,当然,有了这个规定,就可以在垃圾收集器移除死对象的那一刻压缩内存。其余的将位于堆开头的连续块中。
压缩过程使得为新对象顺序分配内存变得更加容易。
GO TO FULL VERSION