如何避免在Tomcat上使用JPA,Hibernate和Spring的Classloader泄漏 [英] How to avoid Classloader Leak with JPA, Hibernate and Spring on Tomcat

查看:104
本文介绍了如何避免在Tomcat上使用JPA,Hibernate和Spring的Classloader泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

开放J2EE Web模板是一个展示应用程序
wicket - 在Tomcat7 servlet容器上运行的Spring和Hibernate的JPA。它的Maven构建脚本似乎以标准方式使用组件。



但是,它从Tomcat中取消部署时,会受到应用程序类加载器内存泄漏的影响。

>

Tomcat的查找泄漏按钮确认泄漏。当使用VM选项-XX:+ HeapDumpOnOutOfMemoryError部署在Tomcat上时,可以使用Eclipse内存分析工具(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.Log ger.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.Abstrac tAutowireCapableBeanFactory.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.configureAndRe freshWebApplicationContext(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)


如果我理解类加载器泄漏:可怕的java.lang.OutOfMemoryError:PermGen空间异常正确,那么这个类加载器泄漏是预期的。



什么是推荐的方法来避免这种情况,或者什么将是一个替代的春季/ JPA
模板web应用程序在Tomcat上吗?

解决方案

Tomcat7 + OpenJPA2上的相同webapp内存泄漏。 4.1 +验证API1.x + hibernate-validator-5.2.1 + jboss-logging。 jar



问题确实是jboss-logging.jar创建了java.util.logging.Level实例的子类。如果jar由J2EE容器提供,但可能会在mywebapp / WEB-INF / lib分发时发生,那么这可能不成问题。 我创建了一个包的分支来禁用子类。问题消失了,webapp热重新部署工作正常。

GC根路径的Heapdump指出问题的根源,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> - 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(粘性类) - class:java.util.logging.Level $ KnownLevel,value:java.util.HashMap#375

编辑为这个bug创建了JBoss Jira票据( https: //issues.jboss.org/browse/JBLOGGING-118


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?

解决方案

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)

这篇关于如何避免在Tomcat上使用JPA,Hibernate和Spring的Classloader泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆