Different classloaders in jdk8 and jdk11
See original GitHub issueI’m upgrading a Spring Boot 2.2.2 application from Java 8 to 11.
I’ve faced some ClassNotFoundExceptions because Java 11 doesn’t include java ee packages, but after adding the missing jars, the application still cannot find the classes if the thread is created using CompletableFuture.
The classloaders in these CompletableFuture-threads are different if you execute with jdk8 or jdk11.
So there are ClassNotFoundException only inside the CompletableFuture thread.
I’ve checked twice the different migration guides and the issues fixed and cannot found this as a regular behavior so i file it as a bug.
/*
* Java 8 http-nio-8080-exec-1 TomcatEmbeddedWebappClassLoader
* Java 11 http-nio-8080-exec-1 TomcatEmbeddedWebappClassLoader
*/
log.info(Thread.currentThread().getName()+" "+Thread.currentThread().getContextClassLoader().toString());
/*
* Java 8 ForkJoinPool.commonPool-worker-1 TomcatEmbeddedWebappClassLoader
* Java 11 ForkJoinPool.commonPool-worker-3 jdk.internal.loader.ClassLoaders$AppClassLoader@5bc2b487 <- it's different and it cannot load the classes even if the classes are in the final jar
*/
CompletableFuture.runAsync(() -> {
log.info(Thread.currentThread().getName()+" "+Thread.currentThread().getContextClassLoader().toString());
}).join();
Related https://github.com/spring-projects/spring-boot/issues/17796
Issue Analytics
- State:
- Created 4 years ago
- Reactions:4
- Comments:5 (2 by maintainers)
Top Results From Across the Web
Transition from Java 8 to Java 11 - Azure - Microsoft Learn
The class loader hierarchy has changed in Java 11. The system class loader (also known as the application class loader) is now an...
Read more >ClassLoader (Java SE 12 & JDK 12 ) - Oracle Help Center
A class loader is an object that is responsible for loading classes. The class ClassLoader is an abstract class. Given the binary name...
Read more >[#LPS-89149] Handle class loader changes in JDK11 which ...
Handle class loader changes in JDK11 which affect NewEnvTestRule ... Also, the bootstrap class loader in JDK11 defines much fewer classes compared to...
Read more >Notes on upgrading from Java 8 to Java 11 - JavaIsland
Internally, the JVM can make use of modules by making class loading more efficient. The result is a smaller, lighter and faster start-up...
Read more >Class Loaders in Java - Baeldung
As we can see, there are three different class loaders here: application, extension, and bootstrap (displayed as null). The application class ...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Parallel streams use the default
ForkJoinPool.commonPoolcausing exact the same problem with class loaders in JDK9, JDK10, JDK11, … Watch out forparallelStream(),parallel()in your code.In my case, it manifested in the error
javax.xml.soap.SOAPException: Unable to create SAAJ meta-factory: Provider com.sun.xml.internal.messaging.saaj.soap.SAAJMetaFactoryImpl not foundafter switching from Java 8 to Java 11.The error only occurred when the application was running packaged as JAR (and not in the Eclipse IDE).
UPDATE 2021-01-21: I ended up using ParallelCollectors (perhaps it can be useful to someone):
before:
now:
The Thread Context Class Loader (TCCL) in the parallel threads is
TomcatEmbeddedWebappClassLoader(whose parent isorg.springframework.boot.loader.LaunchedURLClassLoader). Exactly as it was with JDK8. No class loading problems occure anymore.JAR-packaged stand-alone Spring Boot application (embedded Tomcat), JDK11.
@elab I’ve had same issue with JAX-WS and ForkJoinPool and my workaround way using custom ForkJoinThreadFactory and now it is working fine (https://stackoverflow.com/a/57551188/5599629). And also I had to set
javax.xml.soap.MetaFactoryandjavax.xml.soap.SAAJMetaFactoryandjavax.xml.bind.JAXBContextFactorysystem properties because without ForkJoinPool also it was working OK for couple of requests and after thatClassNotFoundExceptionreturned.(sorry for commenting on closed issue)