【问题标题】:Are objects cleaned up when references to them are nulled?当对它们的引用为空时,是否清理了对象?
【发布时间】:2011-03-17 12:22:37
【问题描述】:
public class App1 
{

 public static void main(String[] args) 
 {
   Point point_1 = new Point(5,5);
   Point point_2 = new Point(7,8);
   Circle circle_1 = new Circle(point_2, 10);
   point_1 = null;
   point_2 = null;
 }
}

此代码执行后存在多少对象引用?为什么?

【问题讨论】:

    标签: java


    【解决方案1】:

    这段代码执行后,完全没有,因为它会退出:-)

    如果您的意思是在退出之前的那一点,则堆栈上有一个对您的圈子的引用,并且您的圈子中有一个对第二个点的引用,假设构造函数存储它。

    【讨论】:

    • 次要问题:编译器可能不会费心将 circle_1 放入堆栈,因为它是一个未使用的本地.....
    【解决方案2】:

    尽管存在公式化问题,但 sn-p 实际上对垃圾可收集性的某些方面很有指导意义。让我们逐行看一下。

     Point point_1 = new Point(5,5);
    

    所以我们声明了一个引用变量point_1,它指向一个new Point。现在让我们假设Point 的构造函数没有做任何花哨的事情,而是简单地使用给定值设置字段final int x, y。

    因此,我们现在有这样的东西:

    现在让我们看看下一行:

    Point point_2 = new Point(7,8);
    

    现在我们有这样的东西:

    现在让我们看看下一行:

    Circle circle_1 = new Circle(point_2, 10);
    

    这里我们也不太清楚Circle 是如何实现的,但可以合理地假设它有final Point center 和final int radius 字段,特别是Point center,它只是将引用设置为给定的Point(即没有防御性复制,因为Point 是不可变的)。

    所以现在我们可能有这样的东西:

    然后在接下来的两个语句中,我们将point_1 和point_2 分别设置为指向null:

    point_1 = null;
    point_2 = null;
    

    所以现在我们有这样的东西:

    我们现在可以观察到:

    • 对象[aPoint(5 5)] 不再可访问
    • [aPoint(7 8)] 对象虽然不再被 point_2 引用,但仍被 [aCircle(10)].center 引用。

    垃圾回收性是由一个对象是否可以被实时引用访问定义的。我们可以强烈假设对象[aPoint(5 5)](基于我们认为Point 的实现方式)不再可访问,因此它有资格被收集(它是垃圾!现在没有人可以“捡起它”!) .

    另一方面,对象[aPoint(7, 8)] 仍然被[aCircle(10)].center 引用,所以我们可以说它不符合收集条件(它不是垃圾!有人还在“挂上”!)。


    道德

    所以不,绝对设置对null 的引用确实不会 使先前被引用的对象自动符合收集条件。这取决于对象本身,是否存在对该对象的任何引用。

    当然,设置对 null 的引用 CAN 有助于使对象符合收集条件,例如当该引用是对象的最后一个剩余时。

    不但是,您必须始终设置对null 的引用以使垃圾收集“有效”。当变量超出范围时,引用不再有效,因此在这种情况下,显式设置为 null 只是多余的代码。

    显式设置为null DOES 的经典示例是Stack 示例:当顶部元素从Stack 弹出时,Stack 不应再引用对象来自其内部数据结构。

    另见

    • 有效的 Java 第 2 版,第 6 条:消除过时的对象引用

    相关问题

    【讨论】:

    【解决方案3】:

    答案是:

    1. 定义对象引用“存在”的含义。
    2. 如果没有 Point 和 Circle 类的详细信息,甚至无法知道创建了多少对象引用。
    3. 答案无关紧要,因为在main 方法退出后,将无法访问任何对象...无论引用是否仍然“存在”。

    我们可以推断,在main 方法返回之前的某个时间点,将有一个对Circle 对象的可达引用和一个对Point 的可达引用。但是人们必须对这两个类是如何实现的做出一些(合理的)假设才能做出这种推断。 (例如,必须假设各自的构造函数没有将Point 和Circle 引用添加到某个静态数据结构中。)

    当对对象的引用为空时,对象是否被清理?

    没有。垃圾收集器运行时会清理对象,并确定相关对象不再可访问。从这个意义上说,“可达”意味着您可以通过以下对象的引用链访问该对象:

    • 某个类的静态属性
    • 某个线程当前正在执行的某个方法的局部变量
    • 某个其他可达对象的属性,或
    • 某个其他可达数组的元素。

    (我稍微简化了对 GC 和可达性的解释,以避免将 OP 与他/她还不理解的东西混淆。)

    【讨论】:

      猜你喜欢
      • 2019-12-01
      • 2017-12-17
      • 1970-01-01
      • 1970-01-01
      • 2014-08-13
      • 2020-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多