A war is deployed to Tomcat 8.5.27. During this deployment, entity classes are dynamically added to a persistence.xml
file on the classpath.
Then Hibernate 5.1.2 is asked to load the persistence unit containing those entity classes. They get added to a java.net.FactoryURLClassLoader
instance. Here is an excerpt from the deployment log showing a dump of this class loader:
[INFO] [talledLocalContainer] 15-Feb-2019 15:03:46.722 INFOS [localhost-startStop-1] org.apache.catalina.core.ApplicationContext.log ** SEARCHING: generated.com.company.Baz
[INFO] [talledLocalContainer] 15-Feb-2019 15:03:46.727 INFOS [localhost-startStop-1] org.apache.catalina.core.ApplicationContext.log ClassLoader: java.net.FactoryURLClassLoader@701f7082
[INFO] [talledLocalContainer] class generated.com.company.Foo
[INFO] [talledLocalContainer] class generated.com.company.Bar
(...)
[INFO] [talledLocalContainer] class generated.com.company.GooClassLoader: ParallelWebappClassLoader
[INFO] [talledLocalContainer] context: webappContext
[INFO] [talledLocalContainer] delegate: false
[INFO] [talledLocalContainer] ----------> Parent Classloader:
[INFO] [talledLocalContainer] java.net.URLClassLoader@45d6cf48
[INFO] [talledLocalContainer]
[INFO] [talledLocalContainer] class com.sun.jersey.server.impl.container.servlet.JerseyServletContainerInitializer
[INFO] [talledLocalContainer] class javax.ws.rs.core.Application
(...)
Please note that all the above actions seem performed by the localhost-startStop-1
thread.
Later, when a request hits the webapp, the thread handling that request (http-nio-8080-exec-6
see in log below) is unable to find the classes under generated.com.company
. Here is an excerpt of the dump of this thread class loader:
[INFO] [talledLocalContainer] 15-Feb-2019 15:04:18.705 INFOS [http-nio-8080-exec-6] org.apache.catalina.core.ApplicationContext.log ** SEARCHING: generated.com.company.Foo
[INFO] [talledLocalContainer] 15-Feb-2019 15:04:18.724 INFOS [http-nio-8080-exec-6] org.apache.catalina.core.ApplicationContext.log ClassLoader: ParallelWebappClassLoader
[INFO] [talledLocalContainer] context: webappContext
[INFO] [talledLocalContainer] delegate: false
[INFO] [talledLocalContainer] ----------> Parent Classloader:
[INFO] [talledLocalContainer] java.net.URLClassLoader@45d6cf48
[INFO] [talledLocalContainer]
[INFO] [talledLocalContainer] class com.sun.jersey.server.impl.container.servlet.JerseyServletContainerInitializer
[INFO] [talledLocalContainer] class javax.ws.rs.core.Application
(...)
Here is the code used to generate the dump:
private static void dumpLoadedClasses() {
try {
ClassLoader myCL = Thread.currentThread().getContextClassLoader();
StringBuilder sb = new StringBuilder();
while (myCL != null) {
sb.append("ClassLoader: " + myCL);
for (Iterator<Class<?>> iter = list(myCL); iter.hasNext();) {
sb.append("\n\t" + iter.next());
}
myCL = myCL.getParent();
}
log.info(sb.toString());
} catch (Exception e) {
log.warn("", e);
}
}
Why http-nio-8080-exec-6
doesn't have java.net.FactoryURLClassLoader@701f7082
as his context class loader ?