Утечки памяти Java - PullRequest
       37

Утечки памяти Java

1 голос
/ 15 декабря 2011

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

По существу:

while(true){
run();
Thread.sleep(day);
}

Через некоторое время я получаю исключения OutOfMemoryHeapException. Прочитав об этом немного, я подумал, потому что любые объекты, созданные внутри метода run (), никогда не будут собираться мусором.

Поэтому я сделал что-то вроде:

public void run(){
Object a = new Object();
a.doSomething();

a= null; //Wasn't here before
}

Мой вопрос: решит ли это мою проблему? У меня сложилось впечатление, что как только объект становится нулевым, объект, на который он ранее ссылался, будет собираться? И это хорошая идея? Или мне стоит заняться чем-то другим?

Спасибо

Ответы [ 8 ]

3 голосов
/ 15 декабря 2011

Добавление a = null почти наверняка будет недостаточным для устранения проблемы (поскольку a все равно выйдет из области видимости).

Мой совет - использовать профилировщик памяти, чтобы точно определить, что и где протекает.

Я лично использую YourKit. Это очень хорошо, но стоит денег (вы можете получить бесплатную оценку).

Еще один недавно выпущенный инструмент - Plumbr. Я еще не попробовал, но реклама говорит:

Попробуйте наш Java-агент для своевременного обнаружения утечек памяти. Мы расскажем вам о том, что происходит с утечкой, откуда происходит утечка и где в данный момент находятся утечки, задолго до OutOfMemoryError!

2 голосов
/ 15 декабря 2011

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

Мой совет: Имитируйте то же поведение с меньшим периодом времени, чтобы вы могли заставить ошибку произойти. Запустите его с помощью профилировщика и посмотрите, куда уходит вся эта память, и работайте оттуда.

0 голосов
/ 15 декабря 2011

В краткосрочной перспективе прагматичный подход к поддержанию стабильности вашего приложения заключается в выходе из JVM после каждого выполнения.Используйте пакетный планировщик (например, cron в * nix, at в Windows) для запуска приложения только один раз в день.Любые утечки памяти будут устранены, когда JVM точно существует.Однако, возможно, вам следует быть осторожным, чтобы не оставить соединения с базой данных открытыми и т. Д.

Это даст вам время для устранения неполадок и устранения основных утечек памяти при сохранении рабочего кода и отсутствии необходимости в поддержке персоналаперезапуск серверов и т. д.

Я предполагаю, что вам не хватает памяти для одного выполнения

0 голосов
/ 15 декабря 2011

Локальные переменные должны быть собраны GC .Таким образом, вам не нужно ставить obj = null; .Потому что объект также хранится в области кучи.

0 голосов
/ 15 декабря 2011

Установка ссылок на null зависит от того, находится ли ваш объект в области действия в течение длительного процесса, хотя теоретически он будет помечать ссылку как null, которую вы не можете гарантировать, когда она будет собирать мусор.

Вам необходимопроверьте, хранятся ли ваши объекты в области видимости где-то в вашем коде.

Нашли хорошее объяснение установки ссылок на null: Делает ли установка объектов Java в null что-нибудь еще?

Чтобы скрыть проблему, вам нужно профилировать приложение.

Поиск SO дал так много указателей на сборщик мусора, что я решил просто разместить строку поиска здесь:

https://stackoverflow.com/search?q=Java+Garbage+collection+and+setting+references+to+null

http://java.sun.com/docs/books/performance/1st_edition/html/JPAppGC.fm.html

0 голосов
/ 15 декабря 2011

Нет.Вам не нужно устанавливать переменную в нуль.Виртуальная машина знает, что вы выходите из этой области и что переменная a больше не существует, поэтому она автоматически уменьшает счетчик ссылок, и ваш объект пригоден для сборки мусора, если у него нет других ссылок.

Ошибка находится где-то еще.

0 голосов
/ 15 декабря 2011

Вы должны получить дамп памяти и проанализировать его с помощью таких инструментов, как JConsole JVisualVM .

Область действия метода run() остается до Thread.sleep(day);, и поэтому любые переменные внутри этого метода уничтожаются. После этого a больше не будет существовать, и, таким образом, объект, на который ссылается эта переменная , может иметь право на сборку мусора , если на него нет другой ссылки .

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

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

Например, у нас была проблема с соединениями с базами данных, которые создавались часто (механизм восстановления XA), и мы думали, что они будут уничтожены, как только область действия метода останется. Тем не менее, сервер поместил эти соединения в статический список и никогда не очищал его, и поэтому у нас действительно не было памяти в ближайшее время. Что помогло нам идентифицировать этот случай, так это анализ дампа памяти. :)

0 голосов
/ 15 декабря 2011

Ваше впечатление неверное.Объекты, созданные внутри метода run (), будут подвергаться сборке мусора при условии, что они 1) выйдут из области видимости и 2) высвободят все ресурсы собственной или удаленной системы, которые они используют.

Какие функции вы фактически выполняете внутри своеговызов метода run ()?Вы читаете файлы, делаете вызовы из базы данных, пишете в сокеты?Не зная деталей, очень трудно предложить лучшее предложение.

...