Ztyx
Ztyx

Reputation: 14898

Memory usage of a large substring?

Reading the source code for String#substring (Java 1.7) it looks like it reuses the character array, but with different offset and length. This means that if I have an giant String that I substring, the initial string will never be reclaimed by GC (right?).

What's the easiest way to sure that the giant String is reclaimed? I am running JavaSE-1.7.

(For the curious, I'll be writing a radix implementation in Java to reduce memory usage. The answer to this question is essential to avoid the radix tree using more memory than necessary)

Upvotes: 1

Views: 398

Answers (2)

justAbit
justAbit

Reputation: 4256

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()

Upvotes: 4

Kartic
Kartic

Reputation: 2985

Original String will always be Garbage Collected if required. No one will object. Here is the partial code for substring() method (JDK 1.7.0_51):

return ((beginIndex == 0) && (endIndex == value.length)) ? this
       : new String(value, beginIndex, subLen);

So, this method is returning a brand new String object or if beginIndex is 0 then the originam String will be returned. I guess you are concerned about first case. In that case, it has nothing to do with the older one once it is created.

Upvotes: 0

Related Questions