如何在Tomcat上使用JPA、Hibernate和Spring避免类加载器泄漏
是的展示应用程序 wicket-JPA,带有Spring和Hibernate,在Tomcat7servlet容器上运行。它的Maven构建脚本似乎以标准方式使用这些组件 但是,当从Tomcat取消部署时,它会受到应用程序类加载器内存泄漏的影响 Tomcat的“查找泄漏”按钮确认泄漏。当使用VM选项-XX:+HeapDumpOnOutOfMemoryError部署在Tomcat上时,可以使用Eclipse内存分析器工具(MAT)分析生成的堆转储。MAT将类如何在Tomcat上使用JPA、Hibernate和Spring避免类加载器泄漏,spring,hibernate,tomcat,jpa,jboss-logging,Spring,Hibernate,Tomcat,Jpa,Jboss Logging,是的展示应用程序 wicket-JPA,带有Spring和Hibernate,在Tomcat7servlet容器上运行。它的Maven构建脚本似乎以标准方式使用这些组件 但是,当从Tomcat取消部署时,它会受到应用程序类加载器内存泄漏的影响 Tomcat的“查找泄漏”按钮确认泄漏。当使用VM选项-XX:+HeapDumpOnOutOfMemoryError部署在Tomcat上时,可以使用Eclipse内存分析器工具(MAT)分析生成的堆转储。MAT将类java.util.logging.Lev
java.util.logging.Level$KnownLevel
标识为阻止垃圾收集的罪魁祸首
对KnownLevel
构造函数的调试显示以下堆栈跟踪:
Level$KnownLevel.add(Level.java:477)
Level.(Level.java:212)
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)
LoggerProviders.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)
Ejb3Configuration(Ejb3Configuration.java:144)
org.hibernate.ejb.HibernatePersistence.createContainerEntityManager工厂(HibernatePersistence.java:74)
org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:268)
org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.AfterPropertieSet(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.PreInstanceSingleton(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)
如果我理解正确,那么这个类加载器泄漏是意料之中的
建议使用什么方法来避免这种情况,或者使用什么替代Spring/JPA
Tomcat上的模板web应用程序?配置除java.util.logging以外的日志框架,例如
如果根本没有配置日志记录,或者配置了java.util.logging,jboss日志记录将通过JDK bug创建类加载器泄漏。查看问题中的堆栈跟踪,jboss logging在何处创建自定义java.util.logging.Level。我在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根路径的Heapdump表示问题的根源,JDKLevel子类在内存中保留一个webapp,很快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
this-value:org.apache.catalina.loader.WebappClassLoader#2
非常感谢你的工作。你会考虑在JBaseLogin项目中提交一个可追踪的问题,这样你的工作最终会成为原始发行的一部分吗?我之所以建议这样做,是因为我面临着其他类加载器问题,我希望生成不会遇到此问题的基本测试用例。@user250343在发现此内存泄漏()后已经完成了此操作。我不知道是否有合适的开发人员看到了我的请求。