另一个字符串的子字符串是否会阻止父字符串被垃圾回收?

Sur*_*raj 1 java garbage-collection

String samplel = "ToBeGarbageCollected";
String sample2 = samplel.substring(0, 1);
samplel = null;
Run Code Online (Sandbox Code Playgroud)

我知道内部的子串将保留原始String的引用.

但是通过明确定义samplelnull,sample1和sample2是否可用于垃圾收集?

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

String samplel = "ToBeGarbageCollected";
String sample2 = new String(samplel .substring(0, 1));
samplel  = null;
Run Code Online (Sandbox Code Playgroud)

Ste*_*n C 6

首先要说的是垃圾收集不会立即发生.因此,分配null给任何东西不会/不会导致垃圾收集.什么是可以做的是使一个对象变得不可达 ...这将使其在未来的GC运行垃圾收集的潜在候选.


现在来看你的具体例子.

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


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

不过话说回来,分配nullsamplel不足以使整个原始字符串的状态无法访问.原始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最终可以查看时,是否仍然可以访问引用...还有关于所讨论的字符串是否足够大且数量足以对内存使用产生重大影响.

并且在实践中,通常不满足该前提条件并且创建一个通常没有帮助的新字符串.