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

标签 java garbage-collection

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

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

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

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

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

最佳答案

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


现在来看你的具体例子。

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


substring 方法不会在新字符串中放置对原始字符串的引用。它实际上做的是保存对原始字符串支持数组的引用;即保存字符的数组。

不过话虽如此,将null赋值给sampell并不足以让整个原始字符串的状态不可达。原始字符串的整个 后备数组将保持可访问性...这意味着它不会成为垃圾收集的候选对象。

但是还有一个问题。您将 sample1 设置为字符串文字,表示字符串文字的字符串对象始终可访问(除非整个类都被卸载!)

But by explicitly defining samplel as null, will sample1 and sample2 be available for garbage Collection?

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

如果 sample1 不是文字并且没有其他引用,那么答案就会不同。 sample1 对象将无法访问,但它的支持数组仍可通过 sample2 访问。


在您的第二个示例中,复制子字符串会导致创建一个新的字符串。并且保证新字符串不会与原始字符串和临时子字符串共享支持数组。在这种情况下,分配 null 是不必要的。

Will now both sample1 and sample2 be available for garbage Collection?

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

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


I just want to know where does String constructor be helpful.

理论上是这样。

在实践中,这取决于当 GC 最终开始查找时引用是否仍然可以访问......以及所讨论的字符串是否足够大和数量足以对内存使用产生重大影响。

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

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

相关文章:

java - 接口(interface)的方法应该抛出异常吗?

java - 模拟 Java 枚举以添加一个值来测试失败案例

javascript - Chrome HTML 页面内存使用情况

AWS Lambda 中的 Python 没有正确垃圾收集?

java - 从 GC 角度来看 Java 流的影响或通过 GC 处理短期对象

python - 已删除的对象仍在 pickle 中引用

Java - CMS 与 G1 垃圾收集器

java - 尝试使用 Eclipse 连接到 MySql 数据库时 Ping 失败

java - 在Java中将代表分钟的Double变量添加到Date中

java - JSP 和商标符号