Based on the discussion about getting substring of String Java String.split memory leak? , I have been analyzing two sample substring examples of usage.
It is said that objects don't get garbage collected if the caller stores a substring of a field in the object. When I run the code I get and OutofMemory Exception, and see the incresing of char[] allocated size while monitoring it via VisualVM
public class TestGC {
private String largeString = new String(new byte[100000]);
String getString() {
return this.largeString.substring(0,2);
//return new String(this.largeString.substring(0,2));
}
public static void main(String[] args) {
java.util.ArrayList<String> list = new java.util.ArrayList<String>();
for (int i = 0; i < 100000; i++) {
TestGC gc = new TestGC();
list.add(gc.getString());
}
}
}
with the following code, I did not get an error and after analyzing memory usage via VisualVM I realized that allocated char[] size getting increasing then somehow decreased at some point , then increasing again and decreased at some point (GC works its job). And It continues forever.
public class TestGC {
private String largeString = new String(new byte[100000]);
String getString() {
//return this.largeString.substring(0,2);
return new String(this.largeString.substring(0,2));
}
public static void main(String[] args) {
java.util.ArrayList<String> list = new java.util.ArrayList<String>();
for (int i = 0; i < 100000; i++) {
TestGC gc = new TestGC();
list.add(gc.getString());
}
}
}
I really want to understand what does GC collect then remove from heap memory in second example? Why GC cannot collect same object in the first example?
at the first example largeString.substring(0,2)); send a reference and at the second example new String(this.largeString.substring(0,2)); creates new objects. Both cases should not problem for behaviour of GC?


substringhas changed since Java7, what Java version are you using?