在通话System.gc()
时可用于垃圾收集的对象是什么?为什么?
public class GCTest {
static class A {
private String myName;
public A(String myName) {
this.myName = myName;
}
}
public static void main(String[] args) {
A a1 = new A("a1");
A a2 = new A("a2");
ArrayList list = new ArrayList();
list.add(a1);
A[] mas = new A[2];
mas[0] = a2;
a2 = a1;
clear(mas);
a1 = null;
a2 = null;
System.gc();
// some code
...
}
private static void clear(A[] mas) {
mas = null;
}
}
如果object == null
变成了垃圾?
我认为a1
,a2
和mas
在调用System.gc()
时可用于垃圾回收,因为它处于null状态。或者我错了?
答案 0 :(得分:8)
首先,您的程序变量永远不会“可用于垃圾回收”。 GC只收集对象,程序变量引用到对象,而不是对象本身。 (引用Java变量的常用术语混淆了这一点。)
其次,a1
,a2
或mas
引用的任何对象都不会被GC化。尽管a1
和a2
已设置为null
,但这是事实。这是因为仍可通过list
或mas
访问对这些对象的引用。为什么a2
引用的对象即使在调用mas
后仍可通过clear()
访问?因为您无法通过将变量传递给方法mas
来更改main()
中变量clear()
的值。您在该方法中所做的只是更改形式参数(也称为mas
),它是main()
中与局部变量分开的变量。 Java严格按值传递。但是,当谈到对象时,总是传递的是引用。
通常,规则是只有当对象无法直接或间接从任何程序变量无法访问时,对象才会被GC。
答案 1 :(得分:2)
没有资格获得GC:
答案 2 :(得分:2)
此时GC没有任何内容可用:
list
)引用包含a1
最初引用的对象的ArrayList(带有" a1"字符串里面的那个)mas
)引用包含a2
最初引用的对象的数组(带有" a2"字符串里面的那个)请注意您的方法
private static void clear(A[] mas) {
mas = null;
}
什么也没做。
Java是按值传递的。因此,在调用此方法时,会创建对该数组的引用的副本并将其传递给该方法。然后,该方法将null指定给原始引用的副本,保持原始引用不变。
答案 3 :(得分:1)
关于对象可达性的唯一指定规则如下(§12.6.1):
可到达对象是任何可以从任何活动线程继续计算中访问的对象。
检查您的代码很明显,在任何可能的持续计算中都可以访问 no 对象。 main
完成后,不存在任何对它们的引用;此外,System.gc()
是程序中的最后一个语句,该语句的计算不会访问那些或任何其他对象(它在Java级别根本没有语义)。因此,无论垃圾收集的实际实现是否实现,所有对象实际上都是无法访问的。
答案 4 :(得分:0)
当您致电System.gc()
时,新A(“a1”),新A(“a2”)和mas创建的对象未被垃圾回收。
线程直接或间接引用的任何对象都不适用于gc。线程正在运行此方法,因此将保留局部变量。
使用new A("a1")
创建的对象(我们称之为A1
)作为示例。
在运行System.gc()时,list
在其内部结构中引用对象A1
,因此即使它未在a1
中引用,也不会进行垃圾回收