web-dev-qa-db-fra.com

Fuite de mémoire Tomcat8

Lorsque j'essaie d'arrêter Tomcat8 sur Java 8, j'obtiens quelques erreurs de fuite de mémoire:

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 [com.util.ThreadLocalProperties$1@2fafda6e]) 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.

La classe ThreadLocalProperties est:

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;
    }
}

et je commence et arrête comme ça:

@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);
    }
}

Pourquoi devrais-je obtenir toutes ces erreurs de fuite de mémoire? de plus, lorsque j'exécute l'arrêt, il ne l'arrête pas, je dois tuer manuellement le processus.

Qu'est-ce qui ne va pas?

19
Dejell

Il n'y a pas de quoi s'inquiéter. Il s'agit d'un message standard émis par Tomcat lorsqu'il détecte que l'application a démarré son propre Thread ou créé un ThreadLocal. Si vous terminez le thread à l'arrêt et supprimez les threadlocals lorsqu'ils ne sont plus nécessaires, alors il n'y aura pas de problème.

Pourquoi devrais-je obtenir toutes ces erreurs de fuite de mémoire? de plus, lorsque j'exécute l'arrêt, il ne l'arrête pas, je dois tuer manuellement le processus.

J'ai vu ce comportement, lorsqu'une application a démarré ScheduledExecutor (mais cela se produira avec tout autre Thread/TheadPool) et je ne l'ai pas arrêtée sur contextDestroyed. Vérifiez donc si vous fermez vos threads à l'arrêt de l'application/du serveur.

Maintenant sur votre problème concret pourquoi le serveur ne s'arrête pas: les pilotes JDBC sont enregistrés dans la JVM en tant que singletons, et sont partagés avec toutes les webapps. Plus d'infos ici. La meilleure solution à votre problème est de déplacer le pilote MySQL dans le /lib dossier. Si vous ne pouvez pas faire cela, vous pouvez essayer this mais cela ressemble plus à un hack qu'à une vraie solution.

19
Svetlin Zarev

Je pense que votre problème est similaire à this . Lorsque vous redéployez l'application, Apache la déploie de manière incrémentielle sur elle-même où system.gc(); ne fonctionne pas et après quelques redéploiements en phase de développement, l'espace généré en permanence est plein et vous obtenez une erreur de fuite de mémoire.

Veuillez continuer à redémarrer votre serveur après quelques redéploiements, afin que l'espace PermGen puisse être effacé avec un redémarrage.

Ou

a vous pouvez également le résoudre en modifiant l'espace PermGen sur le serveur. Veuillez visiter ici .

J'espère que cela t'aidera.

1
Ravi Chhatrala