【问题标题】:Is this garbage-collected or not?这是垃圾收集还是不收集?
【发布时间】:2012-04-18 13:11:10
【问题描述】:

这是一些代码:

public class A {
  private volatile B b;

  public void methodC() {
    b.doSomething();
  }

  public void setB(B newB) {
    this.b = newB;
  }
}

'Thread 1' 正在通过执行 methodC() 来执行 b.doSomething()。

同时'thread 2'设置一个新的B对象到'b'中。

我的问题是:

之前被 'b' 引用的对象是否可以被垃圾回收,尽管它的 doSomething() 方法仍在执行?

【问题讨论】:

    标签: java multithreading garbage-collection


    【解决方案1】:

    不,因为要调用成员函数,您需要引用该对象。因此,调用b.doSomething() 的线程将持有一个引用,从而阻止垃圾回收。

    尽管在下面查看 Jon Harrop 的答案以了解 b 可能是 GC'd 的情况。

    【讨论】:

    • 我认为“线程 1”中没有对先前引用对象的直接或派生引用。我认为 GC 文档中的“可达”意味着必须有一些线程对它有任何直接或派生的引用。
    • 我可以确定的任何参考资料?
    • 为了调用成员函数,必须在线程堆栈中引用对象。这个函数还能怎么调用?
    • 查看StackFrame 类,它代表线程堆栈上的单个帧。它包含对this 对象的引用。
    • 你是对的。我发现了这个:en.wikipedia.org/wiki/… 我误解了 GC 中的可达性。我认为所有可达性都来自变量而不是调用堆栈。感谢您的详细信息:-)
    【解决方案2】:

    之前被 'b' 引用的对象是否可以被垃圾回收,尽管它的 doSomething() 方法仍在执行?

    是的,之前由 'b' 引用的对象可能会被垃圾回收,即使其上的 doSomething() 方法仍在执行。

    您可能期望this 在其方法之一正在执行时是可访问的,因为方法隐式传递了this 指针,并且您可能假设它总是溢出到堆栈中。但是,许多优化可以改变这一点,并从 GC 看到的全局根集中删除 this

    例如,如果doSomething 方法的主体以不需要this 的代码结束并且该方法是内联的,那么this 可能不会从寄存器溢出到堆栈,或者它的堆栈槽可能是覆盖。在这两种情况下,GC 将不再看到 this,即使执行仍在 doSomething 内,因此,this 可能会被垃圾回收。

    【讨论】:

    • +1 啊,我明白你的意思了。我想我在想 this 指针会在 doSomething 中使用,但你是对的 - 如果在该函数中没有对 this 的引用,那么没有什么可以阻止它被 GC 处理。
    • 没错。即使它被使用,它仍然可以在 doSomething 函数中最后一次使用后被回收。
    猜你喜欢
    • 2014-07-24
    • 2010-11-10
    • 2010-12-15
    • 2012-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-29
    • 1970-01-01
    相关资源
    最近更新 更多