一尘不染

如何在Tomcat上通过JPA,Hibernate和Spring避免Classloader泄漏

tomcat

开放的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为阻止垃圾收集的元凶。

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应用程序?


阅读 280

收藏
2020-06-16

共1个答案

一尘不染

我已经在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

2020-06-16