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

Java 另一个字符串的子字符串是否会阻止父字符串被垃圾收集?,java,garbage-collection,Java,Garbage Collection,我知道子字符串内部将保留原始字符串的引用 但是通过将samplel显式定义为null,sample1和sample2是否可用于垃圾收集 我记得在某个地方看到,如果父对象显式设置为null所有子值都可用于垃圾收集。这是否适用于上述情况? 我只是好奇这是否是亲子关系?如果不是,这是否会导致sample1或sample2可用于垃圾收集 String samplel = "ToBeGarbageCollected"; String sample2 = samplel.substring(0, 1); s

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

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

我记得在某个地方看到,如果父对象显式设置为
null
所有子值都可用于垃圾收集。这是否适用于上述情况? 我只是好奇这是否是亲子关系?如果不是,这是否会导致
sample1
sample2
可用于垃圾收集

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

请记住,在Java中,字符串是不可变的。在这种情况下,
sample1
将被丢弃,但
sample2
从未指向
sample1
:它指向JVM中一个单独保存的不可变字符串,该字符串最晚在调用
子字符串时创建

当您将
sample1
设置为null时,它指向的内存可用于垃圾收集(假设没有其他字符串持有相同的值,并且没有其他变量指向该位置)。当您使用
new
关键字(或通过原语的赋值隐式地这样做)时,会在堆上分配新内存(通常,字符串是不可变的,并且共享相同的内存)。如果没有指针(读取:任何命名变量)指向给定的内存位置,则可以对其进行垃圾收集


请记住:在没有对象引用的任何情况下,它都可以用于垃圾收集。对象不是由分配给它们的变量名定义的,而是内存中的位置,变量名充当指向这些对象的指针(引用)。字符串有些不同,因为它们是不可变的,JVM可能会选择不进行垃圾收集,原因与对它们的引用无关。

请记住,在Java
中,字符串是不可变的。在这种情况下,
sample1
将被丢弃,但
sample2
从未指向
sample1
:它指向JVM中一个单独保存的不可变字符串,该字符串最晚在调用
子字符串时创建

当您将
sample1
设置为null时,它指向的内存可用于垃圾收集(假设没有其他字符串持有相同的值,并且没有其他变量指向该位置)。当您使用
new
关键字(或通过原语的赋值隐式地这样做)时,会在堆上分配新内存(通常,字符串是不可变的,并且共享相同的内存)。如果没有指针(读取:任何命名变量)指向给定的内存位置,则可以对其进行垃圾收集


请记住:在没有对象引用的任何情况下,它都可以用于垃圾收集。对象不是由分配给它们的变量名定义的,而是内存中的位置,变量名充当指向这些对象的指针(引用)。字符串有些不同,因为它们是不可变的,JVM可能会选择不进行垃圾收集,原因与对它们的引用无关。

首先要说的是垃圾收集不会立即发生。因此,将
null
赋值给任何对象都不会/不会导致垃圾收集。我们可以做的是使一个对象变得不可访问。。。这将使它成为未来GC运行中垃圾收集的潜在候选


现在来看看你的具体例子

重要注意事项:以下内容仅适用于较旧的JVM;i、 e.Java 7更新5及更早版本。在Java7Update6中,它们更改了
String.substring()
,以便目标字符串和生成的子字符串不共享备份数组。这消除了
子字符串
的潜在存储泄漏问题


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

但是,将
null
赋值给
samplel
不足以使整个原始字符串的状态不可访问。原始字符串的整个支持数组将保持可访问状态。。。这意味着它不会成为垃圾收集的候选对象

但还有另一个复杂因素。将
sample1
设置为字符串文本,表示字符串文本的字符串对象始终是可访问的(除非卸载整个类!)

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

String samplel = "ToBeGarbageCollected";
String sample2 = samplel.substring(0, 1);
samplel = null;
原始的
sample1
对象将保持完全可访问,而
sample2
将保持可访问,除非该变量超出范围

如果
sample1
不是一个文本,并且没有其他引用,那么答案就不同了。
sample1
对象将无法访问,但通过
sample2
仍可以访问其备份数组


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

现在sample1和sample2都可以用于垃圾收集吗

String samplel = "ToBeGarbageCollected";
String sample2 = samplel.substring(0, 1);
samplel = null;
对于
sample1
是文本的情况,答案与上述相同

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


我只是想知道字符串构造函数在哪里有用

理论上是这样的

实际上,这取决于