一尘不染

在最近的JVM中,无形引用仍然是一个问题吗?

java

我正在阅读
Java平台性能
(很遗憾,自从我最初提出这个问题以来,链接似乎已经从互联网上消失了),而A.3.3节使我感到担忧。

我一直在假设一个超出范围的变量将不再被视为GC的根,但是本文似乎与此矛盾。

最近的JVM(尤其是Sun的1.6.0_07版本)是否仍然有此限制?如果是这样,那么我有很多代码需要分析…

我问这个问题是因为该论文来自1999年-有时情况会发生变化,尤其是在GC领域。


由于该论文不再可用,我想换个说法。该文件暗示,在方法退出之前(而不是在代码块结束之前),在方法内部定义的变量将被视为GC根。因此,必须将变量设置为null,以允许对引用的对象进行垃圾收集。

这意味着在main()方法(或包含无限循环的类似方法)的条件块中定义的局部变量将导致一次性内存泄漏,除非您在变量超出范围之前将其清空。

所选答案中的代码很好地说明了这个问题。在文档中引用的JVM版本上,当foo对象在try块末尾超出范围时,不能对其进行垃圾回收。取而代之的是,JVM会一直保持打开引用直到main()方法的结尾,即使任何人都不可能使用该引用。

这似乎是这样的想法的起源,即即使变量将要超出范围,将变量引用为空也将有助于垃圾回收器。


阅读 160

收藏
2020-12-03

共1个答案

一尘不染

此代码应清除它:

public class TestInvisibleObject{
  public static class PrintWhenFinalized{
    private String s;
    public PrintWhenFinalized(String s){
      System.out.println("Constructing from "+s);
      this.s = s;
    }
    protected void finalize() throws Throwable {
      System.out.println("Finalizing from "+s);
    }   
  }
  public static void main(String[] args) {
    try {
        PrintWhenFinalized foo = new PrintWhenFinalized("main");
    } catch (Exception e) {
        // whatever
    }
    while (true) {
      // Provoke garbage-collection by allocating lots of memory
      byte[] o = new byte[1024];
    } 
  }
}

在我的机器(jdk1.6.0_05)上打印:

从主体构造

从主要完成

因此看来问题已得到解决。

请注意,使用System.gc()代替循环不会由于某种原因而导致对象被收集。

2020-12-03