Java:隔离岛

介绍

  在Java中,对象的销毁由GC(垃圾收集器)模块负责,并且那些没有被引用的对象是可以被垃圾收集的,垃圾收集器能够识别这类的对象。
  隔离岛:
  - 对象1引用对象2和对象2引用对象1.对象1和对象2都不被任何其他对象引用。
  - 通常来说隔离岛是一组互相引用但不被应用程序中其它活动的对象引用的对象。严格来说,即使一个没有被引用的对象也是一个隔离岛。
例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Test {
Test i; // 类里定义了一个对象引用
public static void main(String[] args) {
Test t1 = new Test();
Test t2 = new Test();

t1.i = t2;
t2.i = t1;
t1 = null;
t2 = null;
System.gc();
}
@Override
protected void finalize() throws Throwable{
System.out.println("Finalize method called");
}
}

输出:

1
2
Finalize method called
Finalize method called

分析:
  在销毁一个对象之前,垃圾收集器对一个对象最多调用一次finalize方法,在上例中finalize方法被调用两次的理由是因为两个对象都有资格被垃圾收集。这是因为我们在执行t2=null之后没有任何对t1和t2的外部引用。
  我们只有内部的互相引用(在Test类的实例变量i中)。我们没有办法去调用两个对象的实例变量。所以不能再次调用任何一个对象。
  我们在Test类里面创建了一个属性Test i,主函数中创建了两个Test类型的对象,并且用两个引用t1和t2去指向这两个对象,然后通过t1.i去访问t2,通过t2.i去访问t1,直到t2.i = t1: 每个对象都有外部引用t1和t2。这里需要记住的是t1和t2仅仅是引用,真正的对象在图中是以圈表示的,下图中t1指向一个对象,这个对象中有属性i,通过t1这个对象的属性i指向另一个对象,也就是t2指向的对象,反之亦然:

  t1 = null: 此时引用t1已经不指向任何对象,但是对象还是存在的,只不过通过t2.i可以到达之前t1指向的对象,通过t2可以直接访问另一个对象:

  t2 = null: 分析过程和上一步相同,此时没有办法到达任何一个对象:

  现在,两个对象都有资格被垃圾收集,因为我们没有办法调用他们了。这通常被称为隔离岛。

参考资料

GeeksforGeeks