1. Java 垃圾回收概述
垃圾回收(Garbage Collection,GC)是 Java 虚拟机自动管理堆内存的机制,负责识别不再使用的对象并释放其占用的内存。
垃圾回收的触发机制如下:
- 内存不足时: 当 JVM 检测到堆内存不足,无法为新的对象分配内存时,会自动触发垃圾回收。
- 手动请求: 虽然垃圾回收是自动的,开发者可以通过调用 System.gc() 或 Runtime.getRuntime().gc() 建议 JVM 进行垃圾回收。不过这只是一个建议,并不能保证立即执行。
- JVM 参数: 启动 Java 应用时可以通过 JVM 参数来调整垃圾回收的行为,比如:-Xmx(最大堆大小)、-Xms(初始堆大小)等。
- 对象数量或内存使用达到阈值: 垃圾收集器内部实现了一些策略,以监控对象的创建和内存使用,达到某个阈值时触发垃圾回收。
2. Java 垃圾回收判断算法
引用计数法
基本原理: 为每个对象分配一个专有的引用计数器,当一个对象被引用后,计数器 +1,引用失效后,计数器 -1,计数器为 0 时,表示对象不再被任何变量引用,可以被回收。
这个算法非常简单易懂,可是它有一个致命的缺点,就是循环引用的问题。
// 一个简单的循环引用例子
class RefObject {
public Object instance = null;
}
public class Main {
public static void main(String[] args) {
RefObject objA = new RefObject();
RefObject objB = new RefObject();
objA.instance = objB;
objB.instance = objA;
objA = null;
objB = null;
}
}
可以看到,当 objA 和 objB 设置为 null 时,正常来说应该被垃圾回收,可是由于 objA 被 objB 引用,objB 被 objA 引用,导致计数器不为 0 无法被回收,这就是循环引用的问题所在。所以大部分情况我们都是使用下面这种算法。
可达性分析算法
基本原理: 通过一系列称为'GC Roots'的根对象作为起始节点,从这些根节点开始,根据引用关系向下搜索,如果某个对象到 GC Roots 间没有任何引用链相连,则证明此对象是不可用的,可以被回收。


