String samplel = "ToBeGarbageCollected";
String sample2 = samplel.substring(0, 1);
samplel = null;


我知道子字符串内部将保留原始字符串的引用。

但是通过将samplel明确定义为null,sample1和sample2是否可用于垃圾回收?

我记得在某处看到是否将父对象显式设置为null,所有子值都可用于垃圾回收。这对上述内容有好处吗?
我只是好奇这是否是父母子女关系的情景?如果不是,这会导致sample1sample2可用于垃圾收集吗?

String samplel = "ToBeGarbageCollected";
String sample2 = new String(samplel .substring(0, 1));
samplel  = null;

最佳答案

首先要说的是,垃圾回收不会立即发生。因此,将null分配给任何对象不会/不会导致垃圾回收。可能要做的是使对象变得不可访问...,这将使其成为将来GC运行中进行垃圾收集的潜在候选对象。



现在到您的具体示例。

重要说明:以下内容仅适用于较早的JVM;即Java 7 Update 5及更早版本。在Java 7更新6中,他们更改了String.substring(),以便目标字符串和结果子字符串不共享后备数组。这消除了substring潜在的存储泄漏问题。



substring方法不会在新String中放置对原始String的引用。它实际上所做的是保存对原始String的后备数组的引用;即包含字符的数组。

但是,将null分配给samplel不足以使整个原始字符串的状态不可访问。原始String的整个支持数组将保持可访问的状态...这意味着它将不适合进行垃圾回收。

但是还有另一个复杂之处。您将sample1设置为String文字,并且表示String文字的String对象始终可以访问(除非卸载整个类!)


  但是通过将samplel显式定义为null,sample1和sample2是否可用于垃圾回收?


原始的sample1对象将保持完全可访问,而sample2则将保持可访问,除非该变量超出范围。

如果sample1不是文字,并且没有其他引用,则答案将有所不同。 sample1对象将不可访问,但其后备数组仍可通过sample2访问。



在第二个示例中,复制子字符串将导致创建新的String。并且可以确保新的String不会与原始String和临时子字符串共享后备数组。在这种情况下,无需分配null


  现在,sample1和sample2都可用于垃圾回收吗?


对于sample1是文字的情况,答案与上述相同。

如果sample1不是文字,并且没有其他引用,则sample1和临时子字符串现在将不可访问。




  我只想知道String构造函数在哪里有帮助。


从理论上讲将会如此。

在实践中,这取决于GC最终查找时引用是否仍可访问……以及所讨论的字符串是否足够大且足够多,从而对内存使用量产生重大影响。

并且在实践中,通常不满足该先决条件,并且像这样创建一个新的String通常无济于事。

关于java - 另一个字符串的子字符串会阻止父字符串被垃圾回收吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15857883/

10-10 22:21
查看更多