Catalina.out Ошибка утечки памяти
Я все еще вижу эту ошибку в tomcat/logs/catalina.out
,
Dec 29, 2011 4:04:36 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/LoggingMonitor] appears to have started a thread named [Timer-1] but has failed to stop it. This is very likely to create a memory leak.
Dec 29, 2011 4:04:36 PM org.apache.coyote.http11.Http11Protocol destroy
INFO: Stopping Coyote HTTP/1.1 on http-8180
Стоит ли обдумывать, и если да, то как я могу это исправить?
3 ответа
Это, вероятно, не имеет большого значения (просто убить -9 или что-то) и достаточно легко исправить. Просто выясните, какое веб-приложение работает в контексте /LoggingMonitor, а затем найдите его кодовую базу для...
new Timer();
... и заменить их всех...
new Timer( true );
java.util.Timer по умолчанию не запускается в потоках демонов. В ваших веб-приложениях вам нужны таймеры для работы в потоках демона (иначе контейнер не сможет правильно завершить работу, так как ожидает завершения потока таймера, чего он никогда не делает). Найдите все вызовы "new Timer()" и замените их на "new Timer( true)", и жалоба на запись должна прекратиться.
Потратьте некоторое время в JavaDocs, чтобы узнать что-нибудь о потоках daemon vs non daemon: http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Timer.html
Когда я работаю в веб-приложениях, я всегда использую потоки демонов, если в конечном итоге я выполняю какую-то собственную многопоточность. Со средствами в java.util.concurrent это становится очень редким (приходится делать свои собственные потоки).
Наконец, и для записи, я ненавижу java.util.Timer и всегда рекомендую использовать что-то вроде ScheduledExecutor для выполнения периодических, повторяющихся задач. Слишком легко облажаться в Timer и вынимать Tread, на котором он выполняется, демон или иным образом.
Это сообщение не имеет большого значения, если вы всегда останавливаете Tomcat, когда вы удаляете / повторно развертываете свое приложение, в противном случае эти операции вызывают большую утечку памяти, особенно в производственной среде.
Потоки с именем "Timer-#" создаются java.util.Timer (и, возможно, другими классами), как это было предложено Бобом Кухаром, но сглаживание вашей собственной кодовой базы может быть недостаточно, и обеспечение того, что вы используете потоки демона, не устраняет это сообщение комментарий Тома Хотина правильный).
Когда я получил это сообщение, оно было создано транзитивной зависимостью моего кода, именно классом GenericObjectPool
Apache Commons Pool v1.3, который использует поток демона (см. исходный код). Чтобы найти класс, который создает экземпляр Timer, мне пришлось поместить точку взлома в конструктор каждого класса Timer, а затем я проверил стек вызовов. Чтобы решить эту проблему, мне пришлось обновить библиотеку (более новые версии Commons Pool не используют этот таймер).
Если у вас есть контроль над кодом, который создает экземпляр потока, вы можете решить эту проблему, гарантируя, что вы остановите поток при остановке приложения. Использование потоков демонов - хорошая практика, но этого недостаточно, поскольку потоки демонов автоматически умирают только при завершении работы Tomcat, но не при отмене развертывания приложения.
В более общем случае, когда вы не знаете, кто создал неприятный поток, установите флажок " Поиск источника создания потока" в приложении Java и " Определить, кто создал поток" (например, Eclipse).
ОБНОВИТЬ
Совершенно другой подход заключается в использовании очень интересного прослушивателя для предотвращения утечек. Также прочитайте другие посты об утечках classloader от этого автора.