Java中垃圾收集器的工作

时间:2015-08-30 15:45:17

标签: java garbage-collection

在通话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变成了垃圾?

我认为a1a2mas在调用System.gc()时可用于垃圾回收,因为它处于null状态。或者我错了?

5 个答案:

答案 0 :(得分:8)

首先,您的程序变量永远不会“可用于垃圾回收”。 GC只收集对象,程序变量引用到对象,而不是对象本身。 (引用Java变量的常用术语混淆了这一点。)

其次,a1a2mas引用的任何对象都不会被GC化。尽管a1a2已设置为null,但这是事实。这是因为仍可通过listmas访问对这些对象的引用。为什么a2引用的对象即使在调用mas后仍可通过clear()访问?因为您无法通过将变量传递给方法mas来更改main()中变量clear()的值。您在该方法中所做的只是更改形式参数(也称为mas),它是main()中与局部变量分开的变量。 Java严格按值传递。但是,当谈到对象时,总是传递的是引用

通常,规则是只有当对象无法直接或间接从任何程序变量无法访问时,对象才会被GC。

答案 1 :(得分:2)

没有资格获得GC:

  1. 仍然可以访问ArrayList并引用a1
  2. a2a1都指向同一个对象。
  3. 最重要的是,由于Java是按值传递的,因此方法clear实际上清除从mas传递的数组main
  4. 以下是调用GC时内存中对象的说明:

    enter image description here

答案 2 :(得分:2)

此时GC没有任何内容可用:

  • 你仍然有一个引用(list)引用包含a1最初引用的对象的ArrayList(带有" a1"字符串里面的那个)
  • 你仍然有一个引用(mas)引用包含a2最初引用的对象的数组(带有" a2"字符串里面的那个)

请注意您的方法

private static void clear(A[] mas) {
    mas = null;
}

什么也没做。

Java是按值传递的。因此,在调用此方法时,会创建对该数组的引用的副本并将其传递给该方法。然后,该方法将null指定给原始引用的副本,保持原始引用不变。

有关详细说明,请参阅Is Java "pass-by-reference" or "pass-by-value"?

答案 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中引用,也不会进行垃圾回收