小编典典

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

java

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

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

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

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

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

阅读 214

收藏
2020-11-23

共1个答案

小编典典

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


现在到您的具体示例。

重要说明: 以下内容 适用于较早的JVM;即Java 7 update 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最终查找时引用是否仍可访问……以及所讨论的字符串是否足够大且足够多,从而对内存使用量产生重大影响。

并且在实践中, 通常 不满足该前提条件,并且创建这样的新鲜String 通常 无济于事。

2020-11-23