【问题标题】:Garbage Collection and InComplete Constructed Object垃圾收集和不完整的构造对象
【发布时间】:2013-11-16 04:57:55
【问题描述】:

这可能是一个非常幼稚的问题?

假设我有这样的类

class SlowConstructor {

     private final int a;
     private final String unReachableString;

     public SlowConstructor(String random) {
            unReachableString = "I am not reachable will GC will collect me " + random;
            Thread.sleep(1000*3600); // ignoring Exception check for readbility
            a = 100;
            Thread.sleep(1000*3600);
     }
}

所以我的问题是,如果我创建了 SlowConstructor 的许多对象(假设在 diff 线程中创建 50 个),并且如您所见,每个构造函数都需要两个小时才能完成。 SlowConstructor unReachableString 中的字符串引用在大约两个小时内无法从任何代码访问。如果 GC 在这两个小时内运行,它不会收集 unReachableString ref 吗?我认为它不会被垃圾收集,但为什么?从哪里可以访问 unReachableString

【问题讨论】:

标签: java constructor garbage-collection


【解决方案1】:

SlowConstructor unReachableString 中的字符串引用在大约两个小时内无法从任何代码访问。

不正确。 SlowConstructor 对象可以立即从正在构建它的线程访问。因此,是字符串。

这意味着 String 对象在构造函数完成之前不会被垃圾回收。

(事实上,字符串对象对应于一个字符串字面量,因此可以从将方法分配或应用到字面量的代码(任何代码!)中访问。)


可达性 的概念包括任何当前或未来执行可以使用相关对象的机制。这包括对象尚未分配给命名变量或数组元素的情况......尚未。

【讨论】:

  • 谢谢,String 只是一个例子。所以你是说线程持有对 SlowConstructor 的引用,只是我们不能以编程方式访问该引用??
  • 感谢斯蒂芬,我知道我遗漏了一些东西......感谢您的清理。
  • @veritas - 是的。这就是我要说的。在这种情况下,该引用无法以编程方式访问...但它可以访问,因此它是可访问的。
【解决方案2】:

正如其他人所说,GC 不会影响半构造的对象。但为什么? GC 必然从一组最大的根指针开始。从这些根可以到达的任何东西都受到 GC 的“保护”。这要么是我在标记和清除收集器中的标记,要么是通过复制到复制收集器中的新活动代(竞技场)。根由运行时堆栈、机器(虚拟或物理)寄存器和全局指针组成。当构造函数开始运行时,将创建一个指向新分配记录的指针。它要么是根,要么可以从根访问。所以GC不会收集它。由于正在构建的类实例可以从根访问,因此您所指的字符串也是如此。因此也无法收集。

【讨论】:

    【解决方案3】:

    只要线程没有中断,您的对象将(最终)实例化,并(最终)包含unReachableString 的值。

    字符串是interned,只有在没有提及它的情况下才会进行垃圾收集——有点像现在垃圾收集的工作方式。半构造对象确实引用了实习字符串,因此它还没有资格进行垃圾回收。

    我敢打赌,有 50 个左右的这种类型的实例浮动* 也不会产生影响 - 然后你有 50 个左右对这个字符串文字的引用,它还没有资格垃圾收集,直到这些实例本身有资格进行垃圾收集。

    *:哦,上帝​​,请不要在实际代码中这样做

    【讨论】:

      【解决方案4】:

      它不会也不应该被垃圾回收。休眠线程仍然是活动线程。

      Reachable 在 GC 上下文中的含义如下:如果我们遍历 Stack,我们会在 Heap 上找到指向该对象(内存空间)的引用。

      在您的情况下,答案是

      【讨论】:

        【解决方案5】:

        您的逻辑不正确,如果线程仍然存在,则它在方法 SlowConstructor 的范围内。所以 JVM 认为可以使用 unReachableString 字符串,所以 Garbacge Collection 不会触及那个引用。

        根据代码,您可以假设未使用 unReachableString,因此它必须被垃圾收集,但 JVM 没有智能逻辑来知道下一个。它只是看方法和对象引用的范围。

        【讨论】:

          猜你喜欢
          • 2012-07-09
          • 2010-11-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-08-28
          • 2018-04-12
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多