For pre JDK 7u6 version
You should use String(String) constructor in that case:
163 public String(String original) {
164 int size = original.count;
165 char[] originalValue = original.value;
166 char[] v;
167 if (originalValue.length > size) {
168 // The array representing the String is bigger than the new
169 // String itself. Perhaps this constructor is being called
170 // in order to trim the baggage, so make a copy of the array.
171 int off = original.offset;
172 v = Arrays.copyOfRange(originalValue, off, off+size);
173 } else {
174 // The array representing the String is the same
175 // size as the String, so no point in making a copy.
176 v = originalValue;
177 }
178 this.offset = 0;
179 this.count = size;
180 this.value = v;
181 }
String s = "some really looooong text";
String s2 = new String(s.substring(0,3));
When you pass result of s.substring() to String constructor, it will not use char[] of the original String. So the original String can be GC. This is actually one of the use case when one should use String constructor. While in most of the cases we should use String literal assignment.
For JDK 7u6+ version
In Java 7, implementation of String.substring() has been changed, which now internally uses String(char value[], int offset, int count) constructor (which we had to use manually in older version to avoid memory leak). This constructor checks it needs original String's value[] array or a shorter array would be sufficient. So for JDK 7+ using String.substring() will not pose memory leak issue. Please have a look at the source code String.substring()
@nickOfThatPersonin it. Anyway what I was asking about was more about release number. I am interested if it was before or afterJava 1.7.0_06since this behaviour changed then to avoid storing original array which as you noticed couldn't be deleted by GC.Java 1.8.0_45-b14locally.