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

Утечка памяти при перераспределении приложения в Tomcat

При повторном развертывании моего приложения в tomcat возникает следующая проблема:

 The web application [] created a ThreadLocal with key of type
 [java.lang.ThreadLocal] (value [[email protected]])
 and a value of type [com.sun.xml.bind.v2.runtime.property.SingleElementLeafProperty]
(value [[email protected]a183d2]) but 
 failed to remove it when the web application was stopped. 
 This is very likely to create a memory leak.

Кроме того, я использую ehcache в своем приложении. Это также приводит к следующему исключению.

     SEVERE: The web application [] created a ThreadLocal with key of type [null] 
     (value [[email protected]]) and a value of type [java
     .util.WeakHashMap... 

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

Я искал через сеть и нашел это, http://jira.pentaho.com/browse/PRD-3616, но у меня нет доступа к серверу как таковому.

Пожалуйста, дайте мне знать, имеют ли эти предупреждения какое-либо функциональное воздействие или их можно игнорировать? Я использовал параметр "Найти утечки памяти" в диспетчере tomcat, и он говорит "Нет утечек памяти"

4b9b3361

Ответ 1

При повторном развертывании приложения Tomcat создает новый загрузчик классов. Старый загрузчик классов должен быть собран в мусор, иначе вы получите утечку памяти в режиме permgen.

Tomcat не может проверить, будет ли сбор мусора работать или нет, но он знает о нескольких общих точках сбоев. Если загрузчик класса webapp устанавливает ThreadLocal с экземпляром, класс которого был загружен самим загрузчиком класса webapp, поток сервлета содержит ссылку на этот экземпляр. Это означает, что загрузчик классов не будет собирать мусор.

Tomcat выполняет ряд таких обнаружений, см. здесь для получения дополнительной информации. Очистка локаторов потоков затруднительна, вам нужно будет вызвать remove() на ThreadLocal в каждом из потоков, к которым был получен доступ. На практике это важно только во время разработки, когда вы повторно развертываете свое веб-приложение несколько раз. В производстве вы, вероятно, не передислоцируете, поэтому это можно игнорировать.

Чтобы действительно узнать, какие экземпляры определяют локаторы потоков, вы должны использовать профилировщик. Например, курок в JProfiler (отказ от ответственности: моя компания разрабатывает JProfiler) поможет вам найти эти локаторы потоков. Выберите класс объявленных значений (com.sun.xml.bind.v2.runtime.property.SingleElementLeafProperty или com.sun.xml.bind.v2.ClassFactory) и покажите кумулятивные входящие ссылки. Один из них будет java.lang.ThreadLocal$ThreadLocalMap$Entry. Выберите ссылочные объекты для этого ссылочного типа и переключитесь на представление распределения. Вы увидите, где был выделен экземпляр. С помощью этой информации вы можете решить, можете ли вы что-то сделать с этим или нет.

enter image description here

Ответ 2

Маттиас Йидерхамн обладает отличным статья из 6 статей, в которой очень четко объясняется теория и практика утечек загрузчика. Еще лучше, он также выпустил файл jar, который мы можем включить в наши военные файлы. Я попробовал это в своих веб-приложениях, и файл jar работал как шарм! Файл jar называется classloader-leak-prevent.jar. Использовать его так же просто, как просто добавить это в наш web.xml

<listener>
  <listener-class>se.jiderhamn.classloader.leak.prevention.ClassLoaderLeakPreventor</listener-class>
</listener>

а затем добавив это в наш pom.xml

<dependency>
  <groupId>se.jiderhamn</groupId>
  <artifactId>classloader-leak-prevention</artifactId>
  <version>1.15.2</version>
</dependency>

За дополнительной информацией обращайтесь к домашняя страница проекта, размещенная на GitHub или Часть 6 его статьи

Ответ 3

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

Те, кто все еще интересуется быстрым решением/обходным решением, могут пойти ниже:

  • Если вы используете автономный tomcat, запустите javaw.exe или процесс, несущий его.
  • Если вы используете eclipse, запустите eclipse.exe и java.exe или включите процесс.
  • Все еще не разрешено, проверьте, что для диспетчера задач, вероятно, процесс, вызывающий это, будет показан с максимальной памятью использование - Сделайте свой анализ и убейте это.

Вы должны хорошо переделать материал и продолжить работу без проблем с памятью.

Ответ 4

Я предполагаю, что вы, вероятно, видели это, но на всякий случай ehcache doc рекомендует поместить lib в tomcat, а не в WEB-INF/lib: http://ehcache.org/documentation/integrations/tomcat

Ответ 5

Я рекомендую инициализировать локаторы потоков, в ServletRequestListener.

ServletRequestListener имеет 2 метода: один для инициализации и один для уничтожения.

Таким образом, вы можете очистить свой ThreadLocal. Пример:

public class ContextInitiator implements ServletRequestListener {
    @Override
    public void requestInitialized(ServletRequestEvent sre) {
        context = new ThreadLocal<ContextThreadLocal>() {
            @Override
            protected ContextThreadLocal initialValue() {
                ContextThreadLocal context = new ContextThreadLocal();
                return context;
            }
        };
        context.get().setRequest(sre.getServletRequest());
    }
    @Override
    public void requestDestroyed(ServletRequestEvent sre) {
        context.remove();
    }
}

web.xml:

<listener>
    <listener-class>ContextInitiator</listener-class>
</listener>