Ловушки утечки памяти в стандартном API Java
Какие классы API Java Standard могут вызывать утечку памяти при неправильном использовании (не явно)? И как можно избежать/исправлять эти утечки памяти?
Пример: ObjectInputStream
и ObjectOutputStream
хранить ссылки на все объекты, которые они видели, чтобы отправлять последующие вхождения одного и того же объекта в качестве ссылок, а не копий (и тем самым иметь дело с циклическими ссылками), Это приводит к утечке памяти, когда вы держите такой поток открытым неограниченно (например, при его использовании для связи по сети).
Исправить: Вызов reset() периодически или после каждого объекта верхнего уровня.
Ответы
Ответ 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, указанной в качестве основной причины, что затрудняет диагностику.