Lea*_*ner 6 java garbage-collection
1. public class Tahiti {
2. Tahiti t;
3. public static void main(String[] args) {
4. Tahiti t = new Tahiti();
5. Tahiti t2 = t.go(t);
6. t2 = null;
7. // more code here
8. }
9. Tahiti go(Tahiti t) {
10. Tahiti t1 = new Tahiti(); Tahiti t2 = new Tahiti();
11. t1.t = t2; t2.t = t1; t.t = t2;
12. return t1;
13. }
14. }
Run Code Online (Sandbox Code Playgroud)
到达第7行时,有多少对象符合垃圾回收的条件?
根据这个问题给出的答案,第11行没有符合GC资格的对象; 但据我说,至少有一个对象,t2,在第6行设置为null,应该有资格进行垃圾收集.
第6行的变量t2不是对象的唯一引用.从t到对象t2的引用是在函数go中创建的,而对象t2又保持对t1的引用,t1是函数go返回的相同对象.因此,第6行仅减少了引用的数量,但仍然存在对该对象的实时引用.
编辑:让我们尝试更详细的解释,首先我重新编写代码,使解释更容易.每行一个语句和较少混淆的变量名称+我用字母A,B和C标识了三个相关对象.
1. public class Tahiti {
2. Tahiti u;
3. public static void main(String[] args) {
4. Tahiti t = new Tahiti(); // object A
5. Tahiti t2 = t.go(t);
6. t2 = null;
7. // more code here
8. }
9. Tahiti go(Tahiti s) {
10. Tahiti s1 = new Tahiti(); // object B
11. Tahiti s2 = new Tahiti(); // object C
12. s1.u = s2;
13. s2.u = s1;
14. s.u = s2;
15. return s1;
16. }
17. }
Run Code Online (Sandbox Code Playgroud)
在第4行:变量t被初始化以引用新对象.让我们称这个对象本身为A(它通常在java中没有名称,但为了这个解释,它会更容易).
在第5行:t传递给函数go,所以我们转到第9行
在第9行:参数s引用在第4行创建的对象A.
第10行:初始化变量s1以指向对象B.
第11行:初始化变量s2以引用对象C.
第12行:s1.u设置为引用s2,这意味着对象B获得对C的引用
第13行:s2.u设置为引用s1,因此对象C得到对B的引用
第14行:su设置为引用s2,这意味着对象A获得对C的引用,注意C也引用了B,所以此时有一个从A到B的链
第15行返回对象B并返回第5行
第5行:t2设置为参考对象B(B现在直接被t2引用两次,一次因为t指的是引用C的对象A,指的是B)
第6行:引用t2设置为null,因此B丢失一个引用但是t仍然是活的,指向A指的是C指的是B