简体   繁体   English

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

[英]Will a substring of another string prevent the parent string from being garbage collected?

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

I know substring internally will keep a reference for original String. 我知道子字符串内部会保留原始字符串的引用。

But by explicitly defining samplel as null , will sample1 and sample2 be available for garbage Collection? 但是通过将samplel显式定义为null ,是否可以将sample1和sample2用于垃圾回收?

I remember seeing somewhere if a parent object is explicitly set to null all child values are available for garbage collection. 我记得在某处看到是否将父对象显式设置为null所有子值都可用于垃圾回收。 Will this hold good for the above? 这对以上内容有好处吗? I am just curious if this the parent child relationship scenario? 我只是好奇这是否是父母子女关系的情景? If not, will this cause sample1 or sample2 to be available for garbage collection? 如果不是,这会导致sample1sample2可用于垃圾收集吗?

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

First thing to say is that garbage collection doesn't happen immediately. 首先要说的是,垃圾回收不会立即发生。 So assigning null to anything does not / cannot cause garbage collection. 因此,将null分配给任何事物不会/不会导致垃圾回收。 What is may do is to cause an object to become unreachable ... and that will make it a potential candidate for garbage collection in a future GC run. 可能要做的是使对象变得不可访问 ...,这将使其成为将来GC运行中进行垃圾收集的潜在候选对象。


Now to your specific examples. 现在到您的具体示例。

Important Note: the following only applies to older JVMs; 重要说明:以下内容适用于较早的JVM; ie Java 7 update 5 and earlier. 即Java 7 update 5和更早版本。 In Java 7 update 6, they changed String.substring() so that the target string and resulting substring DO NOT share the backing array. 在Java 7更新6中,他们更改了String.substring()以便目标字符串和生成的子字符串不共享后备数组。 This eliminates the potential storage leak issue with substring . 这消除了substring潜在的存储泄漏问题。


The substring method doesn't put a reference to the original String in the new String. substring方法不会在新String中放置对原始String的引用。 What it actually does is save a reference to the original String's backing array; 它实际上所做的是保存对原始String的后备数组的引用; ie the array that holds the characters. 即包含字符的数组。

But having said that, assigning null to samplel is not sufficient to make the state of the entire original string unreachable. 但话虽这么说,为samplel分配null不足以使整个原始字符串的状态不可访问。 The original String's entire backing array will be remain reachable ... and that means it won't be a candidate for garbage collection. 原始String的整个支持数组将保持可访问的状态...这意味着它将不适合进行垃圾回收。

But there is another complication. 但是还有另一个复杂之处。 You set sample1 to a String literal, and the String object that represents a String literal is always reachable (unless the entire class gets unloaded!) 您将sample1设置为String文字,并且表示String文字的String对象始终可以访问(除非卸载整个类!)

But by explicitly defining samplel as null, will sample1 and sample2 be available for garbage Collection? 但是通过将samplel显式定义为null,sample1和sample2是否可用于垃圾回收?

The original sample1 object will remain fully reachable, and sample2 will remain be reachable unless that variable goes out of scope. 除非该变量超出范围,否则原始sample1对象将保持完全可访问,而sample2将保持可访问。

If sample1 had not been a literal and there were no other references to it, then the answer would be different. 如果sample1不是文字,并且没有其他引用,则答案将有所不同。 The sample1 object would be unreachable, but its backing array would still be reachable via sample2 . sample1对象将不可访问,但是其后备数组仍可通过sample2到达。


In your second example, copying the substring causes a new String to be created. 在第二个示例中,复制子字符串将导致创建新的String。 And it is guaranteed that the new String won't share the backing array with the original String and the temporary substring. 并且可以确保新的String不会与原始String和临时子字符串共享后备数组。 In that case, assigning null is unnecessary. 在这种情况下,无需分配null

Will now both sample1 and sample2 be available for garbage Collection? 现在,sample1和sample2都可用于垃圾回收吗?

The answer is the same as for the above for the case where sample1 is a literal. 对于sample1是文字的情况,答案与上述相同。

If sample1 is not a literal and there are no other references to it, then sample1 and the temporary substring would now be unreachable. 如果sample1不是文字,并且没有其他引用,则sample1和临时子字符串现在将不可访问。


I just want to know where does String constructor be helpful. 我只想知道String构造函数在哪里有帮助。

In theory it will be. 从理论上讲将会如此。

In practice it depends on whether the references are still reachable when the GC eventually gets around to looking ... and also on whether the Strings in question are large enough and numerous enough to have a significant impact on memory usage. 在实践中,这取决于GC最终查找时引用是否仍可访问……以及所讨论的字符串是否足够大且足够多,从而对内存使用量产生重大影响。

And in practice, that precondition is usually NOT satisfied and creating a fresh String like that usually does NOT help. 并且在实践中, 通常不满足该前提条件,并且创建这样的新鲜String 通常无济于事。

Remember that in Java String is immutable. 请记住,在Java中String是不可变的。 In this case, sample1 will be discarded, but sample2 never pointed to sample1 : it pointed to a separately held immutable string in the JVM that was created at the latest when substring was called. 在这种情况下, sample1将被丢弃,但是sample2从未指向sample1 :它指向了在JVM中单独保存的不可变字符串,该字符串最晚在调用substring时创建。

When you set sample1 to null, the memory it pointed to became available for garbage collection (assuming no other strings held the same value and no other variables were pointed at that location). 当将sample1设置为null时,它指向的内存可用于垃圾回收(假定没有其他字符串具有相同的值,并且没有其他变量指向该位置)。 When you use the new keyword (or implicitly do so through the assignment of a primitive) new memory is allocated on the heap (usually; again, strings are immutable and share the same memory). 当您使用new关键字(或通过分配基元隐式地使用)时,堆上会分配新的内存(通常;同样,字符串是不可变的,并且共享相同的内存)。 If no pointers (read: any named variables) point to a given location of memory, it is available for garbage collection. 如果没有指针(读取:任何命名变量)指向内存的给定位置,则可用于垃圾回收。

Remember: in any case where there are no references to an object, it becomes available for garbage collection. 请记住:在任何情况下,如果没有对对象的引用,该对象都可用于垃圾回收。 Objects are not defined by the variable names assigned to them, but rather are locations in memory, and the variable names act as pointers (references) to those objects. 对象不是由分配给它们的变量名定义的,而是内存中的位置,并且变量名充当这些对象的指针(引用)。 Strings are somewhat different because they are immutable, and the JVM may opt not to garbage collect for reasons independent of references to them. 字符串有些不同,因为它们是不可变的,并且JVM可能出于与引用无关的原因而选择不进行垃圾回收。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM