2015-05-21 2 views
1

Чтение исходного кода для String#substring (Java 1.7) похоже, что он повторно использует массив символов, но с различным смещением и длиной. Это означает, что если у меня есть гигантский String, что я подстрока, начальная строка никогда не будет восстановлена ​​GC (правда?).Использование памяти большой подстроки?

Что является самым простым способом убедиться, что гигантский String исправлен? Я запускаю JavaSE-1.7.

(Для любопытных, я буду писать реализацию базисной в Java, чтобы уменьшить использование памяти. Ответ на этот вопрос имеет важное значение, чтобы избежать базисного дерева, используя больше памяти, чем это необходимо)

+0

http://stackoverflow.com/questions/20081659/java-substring-memory-leak/20082582#20082582 смотрите на следующее. –

+0

Можете ли вы обновить свой вопрос с помощью точной версии Java, которую используете? – Pshemo

+0

Pshemo: Вопрос обновлен. – Ztyx

ответ

4

Для предварительной версии JDK 7u6 версия

Вы должны использовать String(String) конструктор в этом случае:

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

Когда вы передаете результат s.substring() в String конструктор, он не будет использовать char[] оригинала String. Таким образом, оригинал String может быть GC. На самом деле это один из вариантов использования, когда нужно использовать конструктор String. Хотя в большинстве случаев мы должны использовать литеральное назначение String.

Для JDK 7u6 + версия

В Java 7, реализация String.substring() была изменена, которая в настоящее время используется внутри String(char value[], int offset, int count) конструктор (который мы должны были использовать вручную в старой версии, чтобы избежать утечки памяти). Этот конструктор проверяет, что ему нужен оригинальный массив Stringvalue[] или более короткий массив. Поэтому для JDK 7+ с использованием String.substring() не будет возникать проблема с утечкой памяти. Пожалуйста, посмотрите исходный код String.substring()

+0

Интересно. Строка 'String # String' constuctor выглядит так: https://gist.github.com/JensRantil/7c08a2a0126a8f40c221 Я запускаю JavaSE-1.7. – Ztyx

+0

Да, вы правы. Это связано с тем, что в Java7 они изменили реализацию 'String.substring()', которая теперь внутренне использует 'String (char value [], int offset, int count)' constructor. Пожалуйста, посмотрите исходный код http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7u40-b43/java/lang/String.java#String.substring%28int% 29 –

+0

Спасибо! Отличный ответ! – Ztyx

0

Оригинальная строка всегда будет собираться мусором, если потребуется. Никто не будет возражать. Вот частичный код substring() методы (JDK 1.7.0_51):

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

Таким образом, этот метод возвращает новый объект String, или если beginIndex равен 0, то originam строка будет возвращена. Думаю, вас беспокоит первый случай. В этом случае он не имеет ничего общего со старым, когда он создается.

+1

«Вот неполный код для метода substring():« из какой версии Java этот код? – Pshemo

+1

Там много выпусков Java 7 ... – Pshemo

+0

@Pshemo, я обновил точную версию. Благодаря! Я должен был упомянуть об этом. – Kartic

Смежные вопросы