【问题标题】:What happens to a "finalized" object if I make it available again?如果我再次使“最终”对象可用,会发生什么情况?
【发布时间】:2015-03-09 21:47:50
【问题描述】:

好吧,我尝试让一个最终确定的对象再次可用。我知道(来自oracle docsfinalize() 不会再次被调用。但是如果它变得无法访问会发生什么? 什么时候进行 GC?.

代码:

public class Solution {
static ThreadGroup stg = null;
static Solution ss = null;

protected void finalize() throws Throwable {
    System.out.println("finalized");
    System.out.println("this : " + this);
    ss = this;

}

public static void main(String[] args) {
    Solution s = new Solution();
    s = null;
    System.gc();
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    System.out.println(ss);
    ss = null;             // My question. What happens now?. Solution@7f5f5897 has just become unreachable. Will it be GCed without "finalize()" being called on it? (looks like that..). If yes, then how can I find out when exactly has it become eligible for gc (Please don't tell me to look at source code "==null" check :P)
    System.gc();
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

}

O/P:

finalized
this : Solution@7f5f5897   // printed in finalize()
Solution@7f5f5897  // printed in main()

【问题讨论】:

  • 这叫复活
  • @chrylis - 哦。有趣的是,Oracle 文档没有提到这一点。谢谢:)
  • 我认为这不一定是官方术语,因为您绝对不应该这样做,但这是可能的,并且人们已经设法编写了使 JVM 翻转为一种运动。

标签: java garbage-collection


【解决方案1】:

是的,一旦它第二次变得无法访问,它就会被 GC,除非finalize 不会再次被调用。

您可以通过WeakReference 确认这一点。

static WeakReference<Solution> ref;

public static void main(String[] args) {
    Solution s = new Solution();

    s = null;
    System.gc();
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    System.out.println(ss);
    ref = new WeakReference<Jackson>(ss);
    ss = null; // My question. What happens now?. Solution@7f5f5897 has just become unreachable. Will it be GCed without "finalize()" being called
               // on it? (looks like that..). If yes, then how can I find out when exactly has it become eligible for gc (Please don't tell me to
               // look at source code "==null" check :P)
    System.out.println(ref.get()); // (hopefully) prints object
    System.gc();
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    System.out.println(ref.get()); // prints null
}

所以WeakReferenc 被清除,表明该对象已被GC'ed。 (从技术上讲,当对象变得弱可达时,WeakReference 会被清除。但在这种情况下,由于您无法使其可达,它会被 GC'ed。)

【讨论】:

  • @TheLostMind 你可以在它被 GC'ed 后知道,但没有通知 when
  • 谢谢:)。这确实证明一个对象变得弱可达GCed(逻辑上):P。我仍然没有得到背后的设计决定,只调用一次finalize:P
  • @TheLostMind:finalize 只被调用一次的原因是 每个 被放弃的可终结对象将被复活(创建一个强引用),因为一个强大的finalize 方法运行时引用必须存在。没有任何机制可以将这种复活与更永久的形式区分开来。在 .NET 中有一个方法 ReRegisterForFinalize,如果 Finalize 发现对象还没有准备好死亡,则可以使用该方法,但 Java 中不存在这种机制。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-07-14
  • 2011-03-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-02
  • 1970-01-01
相关资源
最近更新 更多