Java的垃圾回收机制基于以下两个基本概念:
- 引用计数法(Reference Counting):每个对象都有一个引用计数器,当有新的引用指向对象时,计数器加1;当引用失效时,计数器减1。当计数器为0时,表示对象不再被引用,可以被回收。但是,引用计数法无法解决循环引用的问题,即两个或多个对象相互引用,导致计数器永远不为0,造成内存泄漏。
- 可达性分析法(Reachability Analysis):Java的主要垃圾回收算法是基于可达性分析法。它通过从一组称为"GC Roots"的根对象出发,沿着对象之间的引用链进行遍历,标记所有可达的对象。未被标记的对象即为不可达对象,可以被回收。
下面是一个简单的示例,演示了Java的垃圾回收机制:
public class GarbageCollectionExample { public static void main(String[] args) { // 创建两个对象,相互引用 MyClass obj1 = new MyClass(); MyClass obj2 = new MyClass(); obj1.setOther(obj2); obj2.setOther(obj1); // 将obj1和obj2设置为null,断开引用 obj1 = null; obj2 = null; // 手动触发垃圾回收 System.gc(); } } class MyClass { private MyClass other; public void setOther(MyClass other) { this.other = other; } }
在上面的示例中,创建了两个MyClass
对象obj1
和obj2
,并相互引用。然后,将obj1
和obj2
设置为null,断开引用。最后,通过调用System.gc()
手动触发垃圾回收。
当垃圾回收器运行时,它会从GC Roots
(如栈帧中的局部变量、静态变量等)出发,遍历对象之间的引用链。由于obj1
和obj2
互相引用,它们无法被标记为不可达对象,因此不会被回收。但是,如果在main
方法中将obj1
和obj2
设置为null,断开引用,那么它们将成为不可达对象,可以被垃圾回收器回收。
需要注意的是,垃圾回收机制是由Java虚拟机自动管理的,我们一般不需要手动触发垃圾回收。在实际开发中,应该遵循良好的编程习惯,及时释放不再使用的对象的引用,以便垃圾回收器能够及时回收内存,减少内存泄漏的风险。