J'ai configuré Tomcat pour fonctionner avec une source ouverte externe différente.
Cependant, après quelques minutes d’exécution du Tomcat, j’obtiens:
SEVERE: l'application Web [/ MyProject] a créé un ThreadLocal avec clé de type [Java.lang.ThreadLocal] (valeur [Java.lang.ThreadLocal@1b3f02f]) et une valeur de type [org.Apache.axis.MessageContext] (valeur [org.Apache.axis.MessageContext@5dbd4e]), mais ne l'a pas supprimé lorsque l'application Web a été arrêtée. Ceci est très susceptible de créer un fuite de mémoire.
Qu'est-ce qui pourrait le causer?
Où dois-je regarder? Pourrait-il s'agir d'un datapooling sur Tomcat?
Et que signifient les threads dans Tomcat?
ÉDITÉ
Voici ma trace complète. L'application semble recharger son contexte alors qu'elle est toujours en cours d'exécution - et je ne sais pas pourquoi!
Mar 13, 2011 10:56:12 PM org.Apache.catalina.core.StandardContext reload
INFO: Reloading this Context has started
Mar 13, 2011 10:56:12 PM org.Apache.catalina.core.StandardWrapper unload
INFO: Waiting for 1 instance(s) to be deallocated
Mar 13, 2011 10:56:13 PM org.Apache.catalina.core.StandardWrapper unload
INFO: Waiting for 1 instance(s) to be deallocated
Mar 13, 2011 10:56:14 PM org.Apache.catalina.core.StandardWrapper unload
INFO: Waiting for 1 instance(s) to be deallocated
Mar 13, 2011 10:56:14 PM org.Apache.catalina.core.ApplicationContext log
INFO: Closing Spring root WebApplicationContext
Mar 13, 2011 10:56:15 PM org.Apache.catalina.loader.WebappClassLoader clearReferencesJdbc
SEVERE: The web application [/MyProject] registered the JBDC driver [com.mysql.jdbc.Driver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
Mar 13, 2011 10:56:15 PM org.Apache.catalina.loader.WebappClassLoader clearReferencesJdbc
SEVERE: The web application [/MyProject] registered the JBDC driver [Oracle.jdbc.driver.OracleDriver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
Mar 13, 2011 10:56:15 PM org.Apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/MyProject] appears to have started a thread named [NioSocketAcceptor-1] but has failed to stop it. This is very likely to create a memory leak.
Mar 13, 2011 10:56:15 PM org.Apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/MyProject] appears to have started a thread named [NioProcessor-1] but has failed to stop it. This is very likely to create a memory leak.
Mar 13, 2011 10:56:15 PM org.Apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/MyProject] appears to have started a thread named [NioProcessor-4] but has failed to stop it. This is very likely to create a memory leak.
Mar 13, 2011 10:56:15 PM org.Apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/MyProject] appears to have started a thread named [bitronix-disk-force-batcher] but has failed to stop it. This is very likely to create a memory leak.
Mar 13, 2011 10:56:15 PM org.Apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/MyProject] appears to have started a thread named [bitronix-scheduler] but has failed to stop it. This is very likely to create a memory leak.
Mar 13, 2011 10:56:15 PM org.Apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/MyProject] is still processing a request that has yet to finish. This is very likely to create a memory leak. You can control the time allowed for requests to finish by using the unloadDelay attribute of the standard Context implementation.
Mar 13, 2011 10:56:15 PM org.Apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/MyProject] appears to have started a thread named [NioProcessor-7] but has failed to stop it. This is very likely to create a memory leak.
Mar 13, 2011 10:56:15 PM org.Apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/MyProject] appears to have started a thread named [NioProcessor-2] but has failed to stop it. This is very likely to create a memory leak.
Mar 13, 2011 10:56:15 PM org.Apache.catalina.loader.WebappClassLoader clearThreadLocalMap
SEVERE: The web application [/MyProject] created a ThreadLocal with key of type [Java.lang.ThreadLocal] (value [Java.lang.ThreadLocal@1b5a8e1]) and a value of type [org.mvel2.debug.DebuggerContext] (value [org.mvel2.debug.DebuggerContext@16259fd]) but failed to remove it when the web application was stopped. This is very likely to create a memory leak.
Mar 13, 2011 10:56:15 PM org.Apache.catalina.loader.WebappClassLoader clearThreadLocalMap
SEVERE: The web application [/MyProject] created a ThreadLocal with key of type [org.Apache.axis.utils.XMLUtils.ThreadLocalDocumentBuilder] (value [org.Apache.axis.utils.XMLUtils$ThreadLocalDocumentBuilder@84b0b4]) and a value of type [com.Sun.org.Apache.xerces.internal.jaxp.DocumentBuilderImpl] (value [com.Sun.org.Apache.xerces.internal.jaxp.DocumentBuilderImpl@16d2cfa]) but failed to remove it when the web application was stopped. This is very likely to create a memory leak.
Mar 13, 2011 10:56:15 PM org.Apache.catalina.loader.WebappClassLoader clearThreadLocalMap
SEVERE: The web application [/MyProject] created a ThreadLocal with key of type [null] (value [com.Sun.faces.util.Util$1@16bbac9]) and a value of type [Java.util.HashMap] (value [{com.Sun.faces.patternCache={ = }}]) but failed to remove it when the web application was stopped. This is very likely to create a memory leak.
Mar 13, 2011 10:56:15 PM org.Apache.catalina.loader.WebappClassLoader clearThreadLocalMap
SEVERE: The web application [/MyProject] created a ThreadLocal with key of type [Java.lang.ThreadLocal] (value [Java.lang.ThreadLocal@1b3f02f]) and a value of type [org.Apache.axis.MessageContext] (value [org.Apache.axis.MessageContext@5dbd4e]) but failed to remove it when the web application was stopped. This is very likely to create a memory leak.
Mar 13, 2011 10:56:15 PM org.Apache.catalina.loader.WebappClassLoader clearThreadLocalMap
SEVERE: The web application [/MyProject] created a ThreadLocal with key of type [org.Apache.axis.utils.XMLUtils.ThreadLocalDocumentBuilder] (value [org.Apache.axis.utils.XMLUtils$ThreadLocalDocumentBuilder@84b0b4]) and a value of type [com.Sun.org.Apache.xerces.internal.jaxp.DocumentBuilderImpl] (value [com.Sun.org.Apache.xerces.internal.jaxp.DocumentBuilderImpl@378584]) but failed to remove it when the web application was stopped. This is very likely to create a memory leak.
Mar 13, 2011 10:56:15 PM org.Apache.catalina.loader.WebappClassLoader clearThreadLocalMap
SEVERE: The web application [/MyProject] created a ThreadLocal with key of type [org.springframework.core.NamedThreadLocal] (value [Transactional resources]) and a value of type [Java.util.HashMap] (value [{org.hibernate.impl.SessionFactoryImpl@ccc27b=org.springframework.orm.hibernate3.SessionHolder@4f6ada}]) but failed to remove it when the web application was stopped. This is very likely to create a memory leak.
Mar 13, 2011 10:56:15 PM org.Apache.catalina.loader.WebappClassLoader clearThreadLocalMap
SEVERE: The web application [/MyProject] created a ThreadLocal with key of type [null] (value [com.Sun.faces.application.ApplicationAssociate$1@1f01fcf]) and a value of type [com.Sun.faces.application.ApplicationAssociate] (value [com.Sun.faces.application.ApplicationAssociate@1b85528]) but failed to remove it when the web application was stopped. This is very likely to create a memory leak.
2011-03-13 22:57:27,734 ERROR ( ContextLoader.Java:220) - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager' defined in class path resource [applicationContext-hibernate.xml]: Cannot resolve reference to bean 'sessionFactory' while setting bean property 'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in class path resource [applicationContext-hibernate.xml]: Invocation of init method failed; nested exception is Java.lang.OutOfMemoryError: Java heap space
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.Java:328)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.Java:106)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.Java:1325)
Le message est en fait assez clair: quelque chose crée une ThreadLocal
avec une valeur de type org.Apache.axis.MessageContext
- c’est un bon indice. Cela signifie très probablement que le framework Apache Axis a oublié/échoué de se nettoyer après lui-même. Le même problème s'est produit par exemple dans Logback. Cela ne devrait pas vous déranger beaucoup, mais signaler un bogue à l'équipe Axis pourrait être une bonne idée.
Tomcat signale cette erreur car les ThreadLocal
s sont créés par thread de travail HTTP. Votre application n'est pas déployée, mais il reste des threads HTTP - et ceux-ci ThreadLocal
s également. Cela peut entraîner des fuites de mémoire (org.Apache.axis.MessageContext
ne peut pas être déchargé) et quelques problèmes lorsque ces threads sont réutilisés dans le futur.
Pour plus de détails, voir: http://wiki.Apache.org/Tomcat/MemoryLeakProtection
J'ai ajouté ce qui suit à la méthode @PreDestroy dans mon bean CDI @ApplicationScoped et, lorsque j'ai arrêté TomEE 1.6.0 (Tomcat7.0.39, à compter de ce jour), il efface les locales du thread.
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package pf;
import Java.lang.ref.WeakReference;
import Java.lang.reflect.Array;
import Java.lang.reflect.Field;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author Administrator
*
* google-gson issue # 402: Memory Leak in web application; comment # 25
* https://code.google.com/p/google-gson/issues/detail?id=402
*/
public class ThreadLocalImmolater {
final Logger logger = LoggerFactory.getLogger(ThreadLocalImmolater.class);
Boolean debug;
public ThreadLocalImmolater() {
debug = true;
}
public Integer immolate() {
int count = 0;
try {
final Field threadLocalsField = Thread.class.getDeclaredField("threadLocals");
threadLocalsField.setAccessible(true);
final Field inheritableThreadLocalsField = Thread.class.getDeclaredField("inheritableThreadLocals");
inheritableThreadLocalsField.setAccessible(true);
for (final Thread thread : Thread.getAllStackTraces().keySet()) {
count += clear(threadLocalsField.get(thread));
count += clear(inheritableThreadLocalsField.get(thread));
}
logger.info("immolated " + count + " values in ThreadLocals");
} catch (Exception e) {
throw new Error("ThreadLocalImmolater.immolate()", e);
}
return count;
}
private int clear(final Object threadLocalMap) throws Exception {
if (threadLocalMap == null)
return 0;
int count = 0;
final Field tableField = threadLocalMap.getClass().getDeclaredField("table");
tableField.setAccessible(true);
final Object table = tableField.get(threadLocalMap);
for (int i = 0, length = Array.getLength(table); i < length; ++i) {
final Object entry = Array.get(table, i);
if (entry != null) {
final Object threadLocal = ((WeakReference)entry).get();
if (threadLocal != null) {
log(i, threadLocal);
Array.set(table, i, null);
++count;
}
}
}
return count;
}
private void log(int i, final Object threadLocal) {
if (!debug) {
return;
}
if (threadLocal.getClass() != null &&
threadLocal.getClass().getEnclosingClass() != null &&
threadLocal.getClass().getEnclosingClass().getName() != null) {
logger.info("threadLocalMap(" + i + "): " +
threadLocal.getClass().getEnclosingClass().getName());
}
else if (threadLocal.getClass() != null &&
threadLocal.getClass().getName() != null) {
logger.info("threadLocalMap(" + i + "): " + threadLocal.getClass().getName());
}
else {
logger.info("threadLocalMap(" + i + "): cannot identify threadlocal class name");
}
}
}
La clé "Ressources transactionnelles" donne à penser que vous parlez à la base de données sans transaction appropriée. Assurez-vous que la gestion des transactions est configurée correctement et qu’il n’existe aucun chemin d’appel vers le DAO qui ne s’exécute pas sous une annotation @Transactional. Cela peut facilement arriver lorsque vous avez configuré la gestion des transactions au niveau du contrôleur, mais que vous appelez des DAO dans une minuterie ou que vous utilisez des annotations @PostConstruct. Je l'ai écrit ici http://georgovassilis.blogspot.nl/2014/01/Tomcat-spring-and-memory-leaks-when.html
Edit: Il semble que ceci soit (aussi?) Un bogue avec spring-data-jpa qui a été corrigé avec v1.4.3. Je l'ai consultée dans les sources Spring-data-jpa de LockModeRepositoryPostProcessor, qui définissent la clé "Ressources transactionnelles". En 1.4.3, il efface également la clé.
Parfois, cela a à voir avec les changements de configuration. Lors de la mise à niveau de Tomncat 6.0.14 à 6.0.26, nous avions constaté un problème similaire. voici la solution http://www.skill-guru.com/blog/2010/08/22/Tomcat-6-0-26-shutdown-reports-a-web-application-created-a -threadlocal-threadlocal-a-été-forcé-enlevé/
Ce problème apparaît lorsque nous utilisons une solution tierce sans utiliser les gestionnaires pour l’activité de nettoyage. Pour moi, cela se passait pour EhCache. Nous utilisions EhCache dans notre projet pour la mise en cache. Et souvent nous voyions l'erreur suivante dans les journaux
SEVERE: The web application [/products] appears to have started a thread named [products_default_cache_configuration] but has failed to stop it. This is very likely to create a memory leak.
Aug 07, 2017 11:08:36 AM org.Apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/products] appears to have started a thread named [Statistics Thread-products_default_cache_configuration-1] but has failed to stop it. This is very likely to create a memory leak.
Et nous avons souvent remarqué que Tomcat ne parvenait pas à corriger l'erreur OutOfMemory lors du développement, car nous avions l'habitude de modifier le back-end et de déployer l'application plusieurs fois pour refléter nos modifications.
C'est le correctif que nous avons fait
<listener>
<listener-class>
net.sf.ehcache.constructs.web.ShutdownListener
</listener-class>
</listener>
J'essaie donc de vérifier la documentation des bibliothèques tierces que vous utilisez. Ils devraient fournir des mécanismes pour nettoyer les threads lors de l'arrêt. Ce que vous devez utiliser dans votre application . Pas besoin de réinventer la roue à moins que ce ne soit pas fourni par eux. Le pire des cas est de fournir votre propre implémentation.
Référence pour EHCache Shutdown http://www.ehcache.org/documentation/2.8/operations/shutdown.html