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?