垃圾收集 GC(Garbage Collection)是 Java 语言的核心技术之一,之前我们曾专
门探讨过 Java 7 新增的垃圾回收器 G1 的新特性,但在 JVM 的内部运行机制上看,
Java 的垃圾回收原理与机制并未改变。垃圾收集的目的在于清除不再使用的对象。
GC 通过确定对象是否被活动对象引用来确定是否收集该对象。GC 首先要判断该对象
是否是时候可以收集。两种常用的方法是引用计数和对象引用遍历。
引用计数收集器
引用计数是垃圾收集器中的早期策略。在这种方法中,堆中每个对象(不是引用)都
有一个引用计数。当一个对象被创建时,且将该对象分配给一个变量,该变量计数设
置为 1。当任何其它变量被赋值为这个对象的引用时,计数加 1(a = b,则 b 引用的对
象+1),但当一个对象的某个引用超过了生命周期或者被设置为一个新值时,对象的
引用计数减 1。任何引用计数为 0 的对象可以被当作垃圾收集。当一个对象被垃圾收
集时,它引用的任何对象计数减 1。
优点:引用计数收集器可以很快的执行,交织在程序运行中。对程序不被长时间打断
的实时环境比较有利。
缺点: 无法检测出循环引用。如父对象有一个对子对象的引用,子对象反过来引用父
对象。这样,他们的引用计数永远不可能为 0.
跟踪收集器
早期的 JVM 使用引用计数,现在大多数 JVM 采用对象引用遍历。对象引用遍历从一
组对象开始,沿着整个对象图上的每条链接,递归确定可到达(reachable)的对象。
如果某对象不能从这些根对象的一个(至少一个)到达,则将它作为垃圾收集。在对
象遍历阶段,GC 必须记住哪些对象可以到达,以便删除不可到达的对象,这称为标
记(marking)对象。
下一步,GC 要删除不可到达的对象。删除时,有些 GC 只是简单的扫描堆栈,删除未
标记的未标记的对象,并释放它们的内存以生成新的对象,这叫做清除
(sweeping)。这种方法的问题在于内存会分成好多小段,而它们不足以用于新的