У меня есть приложение WebApplication, которое развернуто в Tomcat 7.0.70. Я смоделировал следующую ситуацию:Утечка памяти при повторном развертывании приложения в Tomcat
- Я создал кучу кучи.
- Затем я отправил запрос Http и в методе службы я напечатал текущий поток и его классLoader. И затем я вызвал Thread.currentThread.sleep (10000).
- И в тот же момент я нажал «undeploy это приложение» на странице администрирования Tomcat.
- Я создал новую кучу кучи.
- Через несколько минут я создал новый сброс hep.
РЕЗУЛЬТАТЫ
свалка Thread
На следующем экране вы можете видеть, что после того, как я нажал "перераспределить", все потоки (которые были связаны с этим веб-приложением) были убиты, кроме потока «http-apr-8081-exec-10». Когда я установил атрибут Tomcat «renewThreadsWhenStoppingContext == true», вы можете увидеть, что через некоторое время этот поток («http-apr-8081-exec-10») был убит и новый поток (http-apr-8081-exec-11) был создан вместо него. Поэтому я не ожидал наличия старого WCL после создания кучи dump 3, потому что нет старых потоков или объектов.
Heapd свалка 1
На следующих двух экранах вы можете видеть, что, когда приложение бегала там был только один ВКТ (его параметр «начал» = истина). И в потоке «http-apr-8081-exec-10» был contextClassLoader = URLClassLoader (потому что он был в пуле Tomcat). Я говорю только об этой теме, потому что вы сможете увидеть, что этот поток будет обрабатывать мой будущий HTTP-запрос.
Отправка HTTP запрос
Теперь я отправить запрос HTTP и в моем коде я получаю информацию о текущем thread.You можно увидеть, что мой запрос обрабатывается резьбой «http-apr-8081-exec-10»
дек 23, 2016 9:28:16 AM c.c.c.f.s.r.ReportGenerationServiceImpl INFO: request has been handled in
thread = http-apr-8081-exec-10, its contextClassLoader = WebappClassLoader
context: /hdi
delegate: false
repositories:
/WEB-INF/classes/
----------> Parent Classloader: [email protected]
Затем я нажимаю «Повторное развертывание своего веб-приложения», и я получаю следующее сообщение в консоли.
дек 23, 2016 9:28:27 AM org.apache.catalina.loader.WebappClassLoaderBase clearReferencesThreads
SEVERE: The web application [/hdi] appears to have started a thread named [http-apr-8081-exec-10] but has failed to stop it. This is very likely to create a memory leak.
Heapd свалка 2
На следующих экранах вы можете видеть, что есть два экземпляра WebAppClassLoader. Один из них (номер # 1) является старым (его атрибут «начал» = ложь). И WCL # 2 был создан после повторного развертывания приложения (его атрибут «начал» = true). И нить, которую мы рассматриваем, имеет contextClassLoader = "org.apache.catalina.loader.WebappClassLoader". Почему? Я ожидал увидеть contextClassLoader = "java.net.URLClassLoader" (в конце концов, когда любой поток заканчивает свою работу, он возвращается в пул Tomcat , а его атрибут «contextClassLoader» устанавливается в любой загрузчик базового класса).
Heapd свалка 3
Вы можете увидеть, что там не поточно "HTTP-APR-8081-EXEC-10", но есть поток «http-apr-8081-exec-11», и у него есть contextClassLoader = «WebappClassLoader» (Почему бы не URLClassLoader?).
В конце концов, мы имеем следующее: есть поток «http-apr-8081-exec-11», который имеет ссылку на WebappClassLoader # 1. И obviosly когда я делаю "ближайший GC Root" на ВКТ # 1 Я буду видеть реф к потоку 11.
Вопросы.
Как я могу заставить Tomcat вернуть старое значение contextClassLoader (URLClassLoader) после того, как поток завершит свою работу?
Как я могу убедиться, что Tomcat не копирует старое значение «contextClassLoader» во время обновления потока?
Возможно, вы знаете другой способ решить мою проблему?
Возможный дубликат [Threads in Tomcat. Утечки памяти] (http://stackoverflow.com/questions/41223141/threads-in-tomcat-memory-leaks) –
Если вы не получили достаточного внимания в первый раз, возможно, вы могли бы начать щедрость. Не просто повторно отправляйте тот же вопрос снова. –
@ ChristopherSchultz, этот пост дает больше информации. –