在开放的J2EE Web模板是便门一个展示应用- JPA与Spring和Hibernate是一个Tomcat7 servlet容器运行。它的Maven构建脚本似乎以标准方式使用组件。
但是,当它从Tomcat取消部署时,会受到应用程序类加载器内存泄漏的影响。
Tomcat的“查找泄漏”按钮确认泄漏。当使用VM选项-XX:+ HeapDumpOnOutOfMemoryError部署在Tomcat上时,可以使用Eclipse Memory Analyzer Tool(MAT)分析生成的堆转储。MAT将类标识java.util.logging.Level$KnownLevel为阻止垃圾收集的元凶。
java.util.logging.Level$KnownLevel
KnownLevel构造函数的调试揭示了以下堆栈跟踪:
KnownLevel
java.util.logging.Level $ KnownLevel.add(Level.java:477)java.util.logging.Level。(Level.java:212)java.util.logging.Level。(Level.java:190)组织。 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(Abstractframeworkerbeans.spring.worker.org) factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1514)org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1452)org.springframework.beans.factory.support.AbstractAutowireCapableBean。 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)
如果我理解Classloader泄漏:正确地畏惧了“ java.lang.OutOfMemoryError:PermGen空间”异常,则可以预料到该Classloader泄漏。
建议采用什么方法来避免这种情况,或者在Tomcat上使用替代的Spring / JPA模板Web应用程序?
我已经在Tomcat7 + OpenJPA2.4.1 + ValidationAPI1.x + hibernate-validator-5.2.1 + jboss-logging.jar上看到了相同的webapp内存泄漏
问题确实是jboss- logging.jar创建了java.util.logging.Level实例的子类。如果J2EE容器提供了jar,则可能不是问题,但mywebapp / WEB-INF / lib发行版中会发生这种情况。我创建了一个包的分支以禁用子类化。问题消失了,Webapp热部署工作正常。
GC根路径的堆转储指示问题的根源,JDKLevel子类将Web应用程序保留在内存中,并且JVM很快耗尽了PermGen内存。
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
编辑 为此错误创建的JBoss Jira票证(https://issues.jboss.org/browse/JBLOGGING-118)