It is also possible to sequester memory in ways you don't expect. Consider the following string example.
char[] chars = new char[10_000_000]; // May need to adjust.
String string = new String(chars);
chars = null;
String substring = string.substring(5_000_000);
string = null;
The chars
array may be collected. The array inside string
may not be collected, because substring
contains a reference to the internal array followed by an offset and range into it. So, 107 characters remain allocated, even though only 5 * 106 are used and accessible.
Java 1.7.0_06
It seems that String.substring
no longer has this behavior. In an article in the Java Performance Tuning Guide web site, Mikhail Vorontsov reports that in Java 1.7.0_06 and higher, String.substring
always creates a new String
independent of the old one. The String
class no longer has offset
and range
instance variables. Creating a large string, taking substrings, and throwing away the original will not leave the old string's char[]
sequestered.
// Java 1.7.0_06 and up
char[] chars = new char[10_000_000]; // May need to adjust.
String string = new String(chars);
chars = null;
String substring = string.substring(5_000_000);
// Copies a portion of string's array to a new array.
string = null;
// string's array is no longer reachable, and may be garbage collected.