【问题标题】:Eligible for garbage collection?有资格进行垃圾收集吗?
【发布时间】:2014-06-30 15:08:36
【问题描述】:

我知道内部类的实例必须绑定到包装类的实例,这让我质疑包装类实例在没有对它的引用但仍然有对它的引用时会发生什么绑定实例。

那么,一旦引用设置为 null,otr 引用的对象是否有资格进行垃圾回收?

class Outer
{
    class Inner
    {

    }
}

class Test{
    public static void main(String []args){
        Outer otr = new Outer() ;           // (1)
        Outer.Inner oi = otr.new Inner() ;  // (2)
        otr = null ;                        // (3)
        // more complicated code
    }
}

【问题讨论】:

  • 类的规则基本上与任何其他对象没有什么不同——当它们不再(强)可达时可以释放它们。 (但请注意,“不可达”与“没有引用它”不同。)
  • 因此包装器实例仍然可以通过绑定到它的内部类的实例来访问?使其不符合收集条件?
  • 作为一般规则,除非你在处理“弱”引用或“不安全”之类的东西,否则只要假设 GC 是神奇的,它可以工作,你不必考虑它。

标签: java garbage-collection inner-classes


【解决方案1】:

正如您所说,(非静态)内部类具有对用于创建它的外部类实例的(隐式)引用。因此,在不再(强)引用内部类的实例之前,无法对外部类的实例进行垃圾回收。

【讨论】:

    【解决方案2】:

    如果您查看字节码,您会发现Inner 保留了对Outer 的隐藏引用,该引用由Java 编译器自动生成。

    所以只要oi可以被引用,otr也可以被引用。

    现在您可能认为优化步骤可以消除对Outer 的隐藏引用,因为Inner 从不使用它。但是有人可以扩展Inner 并尝试从那里访问Outer,因此编译器无法做出这样的假设。

    【讨论】:

      【解决方案3】:

      不,在 (1) 中创建的对象无法被垃圾回收。

      在 (2) 中创建的内部类实例持有对对象 (1) 的引用,以便访问它的字段和方法。

      删除第 (3) 行中对对象 (1) 的直接引用不会使对象 (1) 符合垃圾回收条件,因为内部类实例 (2) 仍在(内部)使用对象。

      【讨论】:

        猜你喜欢
        • 2018-06-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-12-10
        • 2011-11-17
        • 1970-01-01
        相关资源
        最近更新 更多