Говорят, что метод substring
в классе String вызывает утечку памяти. Это правда? Как? Что это за альтернатива?
В частности, поиск ответа,
Что это за другие вещи, которые могут вызвать утечку памяти в java? Это поможет мне позаботиться при кодировании.
Метод подстроки в классе String вызывает утечку памяти
Ответ 1
В предыдущих версиях JDK реализация метода substring
создала новый объект String
, сохраняющий ссылку на весь массив char, чтобы избежать его копирования. Таким образом, вы можете случайно ссылаться на очень большой массив символов только с одной строкой символов. Вот пример ошибки, которую это могло бы вызвать.
Этот метод теперь изменен, и эта "утечка" больше не существует.
Если вы хотите использовать старый JDK (который старше, чем OpenJDK 7, Update 6), и вы хотите иметь минимальные строки после substring
, используйте конструктор, который принимает другую строку:
String s2 = new String(s1.substring(0,1));
Что касается вашего второго вопроса, касающегося "других вещей, которые могут вызвать утечку памяти в java", невозможно конструктивно ответить. В java standard libs не существует многих случаев, когда вы могли бы легко скрывать ссылки на объекты. В общем случае обратите внимание на все ссылки, которые вы создаете, наиболее часто возникающие проблемы, возникающие в неочищенных коллекциях или внешних ресурсах (файлы, транзакции базы данных, собственные виджеты и т.д.).
Ответ 2
Метод substring()
не выделяет новый массив символов для String
, а просто создает String
с окном в существующий массив char. Это является следствием мухи и рассматривается как оптимизация.
Итак, если у меня есть огромный массив String
(char), а затем создайте подстроку, даже если я мусор собираю исходную строку, исходный массив char останется (несмотря на то, что вы считаете, что у вас есть подстрока, скажем, 2 символа). Эта проблема часто встречается, когда (скажем) разбор огромного потока входных данных (возможно, файла XML) и извлечение небольшого количества текста через substring()
Использование, казалось бы, избыточного конструктора String(String str)
(конструктор String
с String
!) разрешает это, поскольку он выделяет новый (потенциально меньший) массив char, позволяя оригиналу собирать мусор.
Обратите внимание, что это поведение изменилось с Java 7u6.
Ответ 3
Подстрока строк может привести к сохранению большего объема памяти, чем вы могли ожидать. Таким образом, это не утечка памяти, так как эта память может быть восстановлена в обычном режиме.
Самое простое решение - использовать последнюю версию Java 7, которая этого не делает. Поскольку это единственная свободно поддерживаемая версия от Oracle, вы должны все равно сделать это.
Как таковой он был "исправлен" в обновлении Java 7 5. IMHO это не столько исправление, сколько упрощение реализации. Получение копии каждой подстроки требует гораздо больше работы и, скорее всего, потребляет больше памяти, но это означает, что есть еще одна проблема, о которой нужно беспокоиться.
Что это за другие вещи, которые могут вызвать утечку памяти в java?
Любой объект может быть очищен, поэтому невозможно создать утечку памяти в смысле C/С++. То, что вы можете сделать, это неправильно помещать объекты. Общим примером этого является забывание закрыть ресурсы, такие как ресурс JDBC. Это может привести к сохранению памяти так, как вы не ожидаете.
Ответ 4
В объекте String, когда вы вызываете substring
, свойство value
делится между двумя строками.
Итак, если вы получаете подстроку из большой строки и сохраняете ее в течение длительного времени, большая строка не будет собираться мусором. На самом деле это может привести к утечке памяти.