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

Когда я пытаюсь остановить tomcat8 на Java 8, я получаю несколько ошибок утечки памяти:

org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [ROOT] appears to have started a thread named [Abandoned connection cleanup thread] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
 java.lang.Object.wait(Native Method)
 java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:142)
 com.mysql.jdbc.AbandonedConnectionCleanupThread.run(AbandonedConnectionCleanupThread.java:40)
23-Jan-2015 08:18:10.202 WARNING [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [ROOT] appears to have started a thread named [pool-5-thread-1] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread


23-Jan-2015 08:18:10.205 SEVERE [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.checkThreadLocalMapForLeaks The web application [ROOT] created a ThreadLocal with key of type [com.util.ThreadLocalProperties$1] (value [[email protected]]) and a value of type [java.util.Properties] (value [{}]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.

Класс ThreadLocalProperties:

public class ThreadLocalProperties extends Properties {

    private static final long serialVersionUID = -4260632266508618756L;
    private final ThreadLocal<Properties> localProperties = new ThreadLocal<Properties>() {
        @Override
        protected Properties initialValue() {
            return new Properties();
        }
    };

    public ThreadLocalProperties(Properties properties) {
        super(properties);
    }

    @Override
    public String getProperty(String key) {
        String localValue = localProperties.get().getProperty(key);
        return localValue == null ? super.getProperty(key) : localValue;
    }

    @Override
    public Object setProperty(String key, String value) {
        return localProperties.get().setProperty(key, value);
    }

    public ThreadLocal<Properties> getThreadLocal() {
        return localProperties;
    }
}

и я начинаю и останавливаю его так:

@WebListener()
public class GeneralListener implements ServletContextListener {

    ThreadLocalProperties threadLocalProperties = new ThreadLocalProperties(System.getProperties());

    @Override
    public void contextDestroyed(ServletContextEvent arg0) {
        threadLocalProperties.getThreadLocal().remove();
    }

    @Override
    public void contextInitialized(ServletContextEvent arg0) {
        System.setProperties(threadLocalProperties);
    }
}

Почему я должен получить все ошибки утечки памяти? также, когда я запускаю shutdown, он не закрывает его, я должен вручную убить процесс.

Что не так?

Ответы

Ответ 1

Не о чем беспокоиться. Это стандартный вывод сообщений tomcat, когда он обнаруживает, что приложение запустило его собственный Thread или создало ThreadLocal. Если вы завершаете поток при выключении и удаляете threadlocals, когда они больше не нужны, тогда проблем не будет.

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

Я видел это поведение, когда приложение запустило ScheduledExecutor (но это произойдет с любым другим Thread/TheadPool) и не закрыло его на contextDestroyed. Поэтому проверьте, завершаете ли вы свои потоки при остановке приложения/сервера.

Теперь о вашей конкретной проблеме, почему сервер не останавливается: Драйверы JDBC регистрируются в JVM как одиночные и совместно используются всеми веб-приложениями. Подробнее здесь. Лучшее решение вашей проблемы - переместить драйвер MySQL в папку Tomcat /lib. Если вы не можете этого сделать, вы можете попробовать this, но это скорее похоже на взломать, чем реальное решение.

Ответ 2

Я думаю, что ваша проблема аналогична этому. Когда вы повторно развертываете приложение, apache развертывает его поэтапно на себе, где system.gc(); не работает, и после небольшого перераспределения на этапе разработки постоянное генерируемое пространство заполняется, и вы получаете ошибку утечки памяти.

Перезагрузите сервер после нескольких перераспределений, поэтому пространство PermGen можно очистить при перезагрузке.

Или

a, вы также можете решить его, изменив пространство PermGen на сервере. Пожалуйста, посетите здесь.

Надеюсь, это поможет вам.