垃圾收集和不完整的构造对象

时间:2013-11-16 04:57:55

标签: java constructor garbage-collection

这可能是一个非常天真的问题?

假设我有类似这样的类

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的多个对象(比如差异线程中的50个),你可以看到每个构造函数需要两个小时才能完成。 SlowConstructor unReachableString 中的String引用在任何代码中都无法在大约两小时内到达。如果GC在这两个小时内运行,它将不会收集 unReachableString ref?。我假设它不会被垃圾收集,但为什么呢?从哪里可以访问 unReachableString

5 个答案:

答案 0 :(得分:1)

  

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

不正确的。 SlowConstructor对象可以立即从构建它的线程中到达。因此,就是字符串。

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

(事实上,字符串对象对应于字符串文字,因此可以从代码(任何代码!)中获取,它将方法分配或应用于文字。)


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

答案 1 :(得分:1)

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

答案 2 :(得分:0)

只要线程没有被中断,你的对象就会(最终)实例化,并且(最终)包含unReachableString的值。

字符串是interned,只有在没有引用它的情况下才会进行垃圾收集 - 有点像垃圾收集现在的工作方式。半构造的对象 引用了实习字符串,因此它不符合垃圾回收的条件。

我愿意打赌,这种类型的大约五十个实例漂浮在*周围也不会产生任何影响 - 然后你有大约五十个这个字符串文字的引用,并且它还没有资格垃圾收集,直到这些实例本身有资格进行垃圾收集。

*:OH GOD请不要在实际代码中这样做

答案 3 :(得分:0)

它不会也不应该是垃圾收集。睡眠线程仍然是实时线程。

GC上下文中的

Reachable表示以下内容:如果我们通过Stack,我们会在Heap上找到指向此对象(内存空间)的引用。

在您的情况下,答案是

答案 4 :(得分:0)

你的逻辑不正确,如果线程仍处于活动状态,则它在方法SlowConstructor的范围内。因此JVM认为可以使用unReachableString字符串,因此Garbacge Collection不会触及该引用。

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