JBoss throws a StackOverflowError due to deep recursion in BaseClassLoader
Environment
- JBoss Enterprise Application Platform (EAP) 5
Issue
- JBoss throws a StackOverflowError and the stack trace shows many recursive loops in the BaseClassLoader:
...
at org.jboss.classloader.spi.base.BaseClassLoader.loadClassLocally(BaseClassLoader.java:591)
at org.jboss.classloader.spi.base.BaseClassLoader.loadClassLocally(BaseClassLoader.java:568)
at org.jboss.classloader.spi.base.BaseDelegateLoader.loadClass(BaseDelegateLoader.java:135)
at org.jboss.classloader.spi.filter.FilteredDelegateLoader.loadClass(FilteredDelegateLoader.java:131)
at org.jboss.classloader.spi.base.ClassLoadingTask$ThreadTask.run(ClassLoadingTask.java:455)
at org.jboss.classloader.spi.base.ClassLoaderManager.nextTask(ClassLoaderManager.java:267)
at org.jboss.classloader.spi.base.ClassLoaderManager.process(ClassLoaderManager.java:166)
at org.jboss.classloader.spi.base.BaseClassLoaderDomain.loadClass(BaseClassLoaderDomain.java:276)
at org.jboss.classloader.spi.base.BaseClassLoaderDomain.loadClass(BaseClassLoaderDomain.java:1138)
at org.jboss.classloader.spi.base.BaseClassLoader.loadClassFromDomain(BaseClassLoader.java:862)
at org.jboss.classloader.spi.base.BaseClassLoader.doLoadClass(BaseClassLoader.java:502)
at org.jboss.classloader.spi.base.BaseClassLoader.loadClass(BaseClassLoader.java:447)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632)
at java.lang.ClassLoader.defineClass(ClassLoader.java:616)
at org.jboss.classloader.spi.base.BaseClassLoader.access$200(BaseClassLoader.java:67)
at org.jboss.classloader.spi.base.BaseClassLoader$2.run(BaseClassLoader.java:633)
at org.jboss.classloader.spi.base.BaseClassLoader$2.run(BaseClassLoader.java:592)
at java.security.AccessController.doPrivileged(Native Method)
at org.jboss.classloader.spi.base.BaseClassLoader.loadClassLocally(BaseClassLoader.java:591)
at org.jboss.classloader.spi.base.BaseClassLoader.loadClassLocally(BaseClassLoader.java:568)
at org.jboss.classloader.spi.base.BaseDelegateLoader.loadClass(BaseDelegateLoader.java:135)
at org.jboss.classloader.spi.filter.FilteredDelegateLoader.loadClass(FilteredDelegateLoader.java:131)
at org.jboss.classloader.spi.base.ClassLoadingTask$ThreadTask.run(ClassLoadingTask.java:455)
at org.jboss.classloader.spi.base.ClassLoaderManager.nextTask(ClassLoaderManager.java:267)
at org.jboss.classloader.spi.base.ClassLoaderManager.process(ClassLoaderManager.java:166)
at org.jboss.classloader.spi.base.BaseClassLoaderDomain.loadClass(BaseClassLoaderDomain.java:276)
at org.jboss.classloader.spi.base.BaseClassLoaderDomain.loadClass(BaseClassLoaderDomain.java:1138)
at org.jboss.classloader.spi.base.BaseClassLoader.loadClassFromDomain(BaseClassLoader.java:862)
at org.jboss.classloader.spi.base.BaseClassLoader.doLoadClass(BaseClassLoader.java:502)
at org.jboss.classloader.spi.base.BaseClassLoader.loadClass(BaseClassLoader.java:447)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632)
at java.lang.ClassLoader.defineClass(ClassLoader.java:616)
at org.jboss.classloader.spi.base.BaseClassLoader.access$200(BaseClassLoader.java:67)
at org.jboss.classloader.spi.base.BaseClassLoader$2.run(BaseClassLoader.java:633)
at org.jboss.classloader.spi.base.BaseClassLoader$2.run(BaseClassLoader.java:592)
at java.security.AccessController.doPrivileged(Native Method)
at org.jboss.classloader.spi.base.BaseClassLoader.loadClassLocally(BaseClassLoader.java:591)
at org.jboss.classloader.spi.base.BaseClassLoader.loadClassLocally(BaseClassLoader.java:568)
...
Resolution
- Confirm it is expected behavior through classloader trace logging
- Increase stack size as necessary
Root Cause
- This is most likely expected recursion
- For a class to be loaded, all classes that it extends and all interfaces that it implements must also be loaded. These super classes and interfaces are loaded through recursive classloader calls as seen here. If there is a long chain of extended classes and/or implemented interfaces, the resulting classloader call stack could be quite large.
Diagnostic Steps
- Capture TRACE classloader logging. To enable this, add the following to your jboss-log4j.xml:
<category name="org.jboss.classloader">
<priority value="TRACE"/>
</category>
- Also ensure your appender uses the %t option in its ConversionPattern so that thread names are included, allowing classloader activity to be correlated to the StackOverflowError throwing thread, for example:
<appender name="FILE" class="org.jboss.logging.appender.DailyRollingFileAppender">
...
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n"/>
</layout>
</appender>
Components
Category
Tags
This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.