Подтвердить что ты не робот

Ловушки утечки памяти в стандартном API Java

Какие классы API Java Standard могут вызывать утечку памяти при неправильном использовании (не явно)? И как можно избежать/исправлять эти утечки памяти?

Пример: ObjectInputStream и ObjectOutputStream хранить ссылки на все объекты, которые они видели, чтобы отправлять последующие вхождения одного и того же объекта в качестве ссылок, а не копий (и тем самым иметь дело с циклическими ссылками), Это приводит к утечке памяти, когда вы держите такой поток открытым неограниченно (например, при его использовании для связи по сети).

Исправить: Вызов reset() периодически или после каждого объекта верхнего уровня.

4b9b3361

Ответ 1

Большим является то, что получение подстрок строк Java относится к исходной строке.

Пример: вы читаете 3000-символьную запись и получаете подстроку из 12 символов, возвращая ее вызывающему (в пределах одной JVM). Даже если у вас нет прямой ссылки на исходную строку, эта 12-символьная строка все еще использует 3000 символов в памяти.

Для систем, которые получают и затем анализируют множество сообщений, это может быть реальной проблемой.

У вас есть несколько способов избежать этого:

String sub = new String(str.substring(6,12));

или

String sub = str.substring(6,12).intern();

Первое более четкое. Второе имеет другие последствия, потому что вы используете пространство PermGen. Из-за чрезмерного использования вы можете закончиться, если вы не предоставите свою виртуальную машину достаточно.

Помните, что это актуально только в том случае, если вы берете небольшие подстроки, а затем выбрасываете исходную строку, и вы делаете это много.

Ответ 2

Все, что вы регистрируете в качестве получателя события, например. в рамках GUI, не может собираться мусор, пока он зарегистрирован, а источник события жив.

Это может привести к утечке памяти, если разработчик не знает об этом сильная ссылка от источника события на подписчика событий.

Ответ 3

Любые нестатические внутренние классы, которые вы выполняете для внешних классов. Таким образом, невинный внешний класс может удерживаться на огромном объектном графе. Поместите экземпляр в статическую или общепринятую коллекцию где-нибудь, и вы используете много памяти, которую вы не должны использовать.

Ответ 4

Каждый экземпляр Thread выделяет память для стека (по умолчанию 512k, настраивается через -Xss). Это не утечка как таковая, но наивная попытка сильно многопоточного приложения приведет к значительному неочевидному потреблению памяти.

Ответ 5

Любой класс с методом dispose()?

Например java.awt.Window # dispose:

public void dispose()

Освобождает все ресурсы экрана, используемые этим окном, его подкомпонентами и всеми его дочерними пользователями. То есть ресурсы для этих Компонентов будут уничтожены, любая память, которую они потребляют, будет возвращена ОС, и они будут отмечены как не отображаемые.

Ответ 6

Использование сильных ссылок, когда слабых ссылок было бы достаточно. Приложения и API, которые выполняют свое собственное управление ресурсами и ресурсами, являются обычными преступниками здесь.

Затем используется шаблон Observer, который может привести к утечкам памяти - когда Observer отделяет себя от объекта, память не может быть восстановлена, если Тема также не выпустит ссылку на Observer/Listener. Об этом уже говорилось ранее, но не многие люди понимают, что даже лесорубы являются наблюдателями.

Кроме того, существует вероятность того, что классы, объекты которых при создании экземпляра автоматически помещаются в статический элемент. Некоторые из этих классов даже не имеют метода release() или метода dispose(), поэтому ссылки продолжают удерживаться статическим членом. Это разнообразие утечек памяти в конечном итоге приводит к ошибке OutOfMemory с проблемой пространства PermGen, указанной в качестве основной причины, что затрудняет диагностику.