如何在Tomcat上使用JPA、Hibernate和Spring避免类加载泄漏问题

6 浏览
0 Comments

如何在Tomcat上使用JPA、Hibernate和Spring避免类加载泄漏问题

Open J2EE Web Template是一个使用wicket - 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)

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)

如果我正确理解Classloader泄露:可怕的“java.lang.OutOfMemoryError: PermGen space”异常,那么应该预期会出现这种类加载器泄露情况。应该采取哪种方法来避免这种情况,或者在Tomcat上有哪种Spring/JPA模板Web应用程序的替代方法?

admin 更改状态以发布 2023年5月21日
0
0 Comments

配置一个日志框架,而不是java.util.logging,例如,Logback

如果没有配置任何日志,或者配置了java.util.logging,则jboss logging将通过JDK bug Level.known can leak memory创建一个类加载器泄漏。请查看问题中的堆栈跟踪,其中jboss logging创建了自定义的java.util.logging.Level。

0
0 Comments

我曾在Tomcat7 + OpenJPA2.4.1 + ValidationAPI1.x + hibernate-validator-5.2.1 + jboss-logging.jar上看到过同样的webapp内存泄漏问题。

问题在于,确实是jboss-logging.jar创建了java.util.logging.Level实例的一个子类。如果该jar由J2EE容器提供,则可能不是问题,但是如果是由mywebapp/WEB-INF/lib发布,则会有这个问题。我已经创建了一个软件包的分支来禁用子类化(链接)。问题消失,webapp热重新部署工作正常。

GC根路径的堆转储表明问题的来源,JDKLevel子类会保留一个webapp在内存中,并很快使JVM耗尽PermGen内存。

this     - value: org.apache.catalina.loader.WebappClassLoader #2
 <-      - class: org.jboss.logging.JDKLevel, value: org.apache.catalina.loader.WebappClassLoader #2
  <-      - 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票证来解决这个问题(链接

0