Краткая версия: если вы вызываете string.substring(n, m).intern(), сохраняет ли таблица строк подстроку или исходную строку?
... Но я не уверен, что правильный вопрос спросить, так вот длинная версия:
Я работаю с устаревшим Java-кодом (PCGen), который анализирует файлы, разбивая их как одну большую строку, а затем используя String.split,.trim,.substring и StringTokenizer, чтобы разложить их на токены. Это очень эффективно для синтаксического анализа, потому что ни один из этих методов не копирует исходную строку, но все указывает на части общего char [].
После завершения синтаксиса я хочу вернуть некоторую память. Нужно лишь несколько небольших подстрок оригинальной большой строки, но сильная ссылка не позволяет собирать большую строку. И позже я страдаю OOM, я полагаю, отчасти из-за этого огромного влияния кучи множества проанализированных файлов.
Я знаю, что я могу обрезать большую строку вниз с помощью new String(String)
(copy-on-write). И я знаю, что могу уменьшить дублирование строк через String.intern(что важно, потому что в анализируемых файлах много избыточности). Нужно ли использовать оба, чтобы восстановить наибольшее количество кучи, или делает .intern() и то и другое? Читая исходный код OpenJDK7 hotspot (hotspot/src/share/vm/classfile/symbolTable.cpp), похоже, что таблица строк хранит целую строку и вообще не обрезает ее для смещения/длины. Поэтому я думаю, что мне нужно создать новую String, а затем стажер. Правильно?
Все сказанное, переключение на потоковый синтаксический анализатор будет большой победой в плане памяти, но это слишком большое изменение на короткий срок.