How to avoid Classloader Leak with JPA, Hibernate and Spring on Tomcat

て烟熏妆下的殇ゞ 提交于 2019-12-09 00:08:10

问题


The Open J2EE Web Template is a showcase application for wicket - JPA with Spring and Hibernate that runs on a Tomcat7 servlet container. Its Maven build script appears to use the components in a standard way.

However, it is affected by an application classloader memory leak when it is undeployed from Tomcat.

Tomcat's "Find Leaks" button confirms the leak. When deployed on Tomcat with VM option -XX:+HeapDumpOnOutOfMemoryError, the generated heap dump can be analysed with Eclipse Memory Analyzer Tool (MAT). MAT identifies the class java.util.logging.Level$KnownLevel as the culprit that prevents garbage collection.

Debugging of the KnownLevel constructor reveals the following stack trace:

java.util.logging.Level$KnownLevel.add(Level.java:477) java.util.logging.Level.(Level.java:212) java.util.logging.Level.(Level.java:190) org.jboss.logging.JDKLevel.(JDKLevel.java:35) org.jboss.logging.JDKLevel.(JDKLevel.java:42) org.jboss.logging.JDKLogger.translate(JDKLogger.java:78) org.jboss.logging.JDKLogger.isEnabled(JDKLogger.java:85) org.jboss.logging.Logger.debugf(Logger.java:563) org.jboss.logging.LoggerProviders.find(LoggerProviders.java:37) org.jboss.logging.LoggerProviders.(LoggerProviders.java:32) org.jboss.logging.Logger.getLogger(Logger.java:2163) org.jboss.logging.Logger.getMessageLogger(Logger.java:2259) org.jboss.logging.Logger.getMessageLogger(Logger.java:2214) org.hibernate.ejb.Ejb3Configuration.(Ejb3Configuration.java:144) org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:74) org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:268) org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:310) org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1514) org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1452) org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519) org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456) org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294) org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225) org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291) org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193) org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:567) org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:913) org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464) org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:385) org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:284) org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:111) org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4939)

If I understand Classloader leaks: the dreaded "java.lang.OutOfMemoryError: PermGen space" exception correctly, then this classloader leak is to be expected.

What would be the recommended method to avoid this, or what would be an alternative Spring/JPA template web application on Tomcat?


回答1:


I have seen this same webapp memory leak on Tomcat7 + OpenJPA2.4.1 + ValidationAPI1.x + hibernate-validator-5.2.1 + jboss-logging.jar

Problem is indeed jboss-logging.jar creates a subclass of java.util.logging.Level instances. May not be a problem if jar is provided by J2EE container but will happen with mywebapp/WEB-INF/lib distribution. I have created a fork of package to disable subclassing. Problems went away and webapp hot redeployments work fine.

Heapdump of GC root path indicates a source of problem, JDKLevel subclass keeps a webapp in memory and soon JVM run out of PermGen memory.

this     - value: org.apache.catalina.loader.WebappClassLoader #2
 <- <classLoader>     - class: org.jboss.logging.JDKLevel, value: org.apache.catalina.loader.WebappClassLoader #2
  <- <class>     - class: org.jboss.logging.JDKLevel, value: org.jboss.logging.JDKLevel class JDKLevel
   <- levelObject     - class: java.util.logging.Level$KnownLevel, value: org.jboss.logging.JDKLevel #6
    <- [1]     - class: java.lang.Object[], value: java.util.logging.Level$KnownLevel #12
     <- elementData     - class: java.util.ArrayList, value: java.lang.Object[] #5160 (10 items)
      <- value     - class: java.util.HashMap$Entry, value: java.util.ArrayList #3532
       <- [0]     - class: java.util.HashMap$Entry[], value: java.util.HashMap$Entry #21639
        <- table     - class: java.util.HashMap, value: java.util.HashMap$Entry[] #280 (16 items)
         <- intToLevels (sticky class)     - class: java.util.logging.Level$KnownLevel, value: java.util.HashMap #375

edit Created JBoss Jira ticket for this bug (https://issues.jboss.org/browse/JBLOGGING-118)




回答2:


Configure a logging framework other than java.util.logging e.g. Logback.

If no logging is configured at all, or if java.util.logging is configured, jboss logging will create a classloader leak via the JDK bug Level.known can leak memory. See the stack trace in the question where jboss logging creates the custom java.util.logging.Level.



来源:https://stackoverflow.com/questions/18248502/how-to-avoid-classloader-leak-with-jpa-hibernate-and-spring-on-tomcat

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!