Petals ESB Container

In Java 11, AppClassLoader is no more a URLClassLoader

Details

  • Type: Task Task
  • Status: Resolved Resolved
  • Priority: Critical Critical
  • Resolution: Fixed
  • Affects Version/s: 5.2.0
  • Fix Version/s: 5.3.0
  • Component/s: Classloader
  • Security Level: Public
  • Description:
    Hide

    According to the following Java 11 migration guide: https://nipafx.dev/java-11-migration-guide/

    Java 9 and the module system improved the platform's class loading strategy, which is implemented in a new type and in Java 11 the application class loader is of that type. That means it is not a URLClassLoader, anymore, so the occasional (URLClassLoader) getClass().getClassLoader() or (URLClassLoader) ClassLoader.getSystemClassLoader() sequences will no longer execute. This is another typical example where Java 11 is backwards compatible in the strict sense (because that it's a URLCassLoader was never specified) but which can nonetheless cause migration challenges.

    Symptoms

    This one is very obvious. You'll get a ClassCastException complaining that the new AppClassLoader is no URLClassLoader:

    Exception in thread "main" java.lang.ClassCastException:
    	java.base/jdk.internal.loader.ClassLoaders$AppClassLoader
    	cannot be cast to java.base/java.net.URLClassLoader
    		at monitor.Main.logClassPathContent(Main.java:46)
    		at monitor.Main.main(Main.java:28)

    Fixes

    The class loader was probably cast to access methods specific to URLClassLoader. If so, you might have to face some serious changes.

    If you want to access the class path content, check the system property java.class.path and parse it:

    String pathSeparator = System
    	.getProperty("path.separator");
    String[] classPathEntries = System
    	.getProperty("java.class.path")
    	.split(pathSeparator);

    If you've used the URLClassLoader to dynamically load user provided code (for example as part of a plugin infrastructure) by appending to the class path, then you have to find a new way to do that as it can not be done with Java 11. You should instead consider creating a new class loader for that. This has the added advantage that you'll be able to get rid of the new classes as they are not loaded into the application class loader. You should also read up on layers - they give you a clean abstraction for loading an entirely new module graph.

    Beyond that, your chances to do a migration with only small changes are slim. The only supported (and hence accessible) super types of the new AppClassLoader are SecureClassLoader and ClassLoader and only few methods were added here in 9. Still, have a look, they might do what you're looking for.

    Consequently all common dependencies available in the entry 'Class-Path' of the JAR 'petals-bootstrap-launcher' are no more available for CXF Dynamic client used by the Petals SE Flowable through the Flowable's module 'flowable-cxf', specially JAXB dependencies (see PETALSDISTRIB-474).

    Show
    According to the following Java 11 migration guide: https://nipafx.dev/java-11-migration-guide/
    Java 9 and the module system improved the platform's class loading strategy, which is implemented in a new type and in Java 11 the application class loader is of that type. That means it is not a URLClassLoader, anymore, so the occasional (URLClassLoader) getClass().getClassLoader() or (URLClassLoader) ClassLoader.getSystemClassLoader() sequences will no longer execute. This is another typical example where Java 11 is backwards compatible in the strict sense (because that it's a URLCassLoader was never specified) but which can nonetheless cause migration challenges. Symptoms This one is very obvious. You'll get a ClassCastException complaining that the new AppClassLoader is no URLClassLoader:
    Exception in thread "main" java.lang.ClassCastException:
    	java.base/jdk.internal.loader.ClassLoaders$AppClassLoader
    	cannot be cast to java.base/java.net.URLClassLoader
    		at monitor.Main.logClassPathContent(Main.java:46)
    		at monitor.Main.main(Main.java:28)
    Fixes The class loader was probably cast to access methods specific to URLClassLoader. If so, you might have to face some serious changes. If you want to access the class path content, check the system property java.class.path and parse it:
    String pathSeparator = System
    	.getProperty("path.separator");
    String[] classPathEntries = System
    	.getProperty("java.class.path")
    	.split(pathSeparator);
    If you've used the URLClassLoader to dynamically load user provided code (for example as part of a plugin infrastructure) by appending to the class path, then you have to find a new way to do that as it can not be done with Java 11. You should instead consider creating a new class loader for that. This has the added advantage that you'll be able to get rid of the new classes as they are not loaded into the application class loader. You should also read up on layers - they give you a clean abstraction for loading an entirely new module graph. Beyond that, your chances to do a migration with only small changes are slim. The only supported (and hence accessible) super types of the new AppClassLoader are SecureClassLoader and ClassLoader and only few methods were added here in 9. Still, have a look, they might do what you're looking for.
    Consequently all common dependencies available in the entry 'Class-Path' of the JAR 'petals-bootstrap-launcher' are no more available for CXF Dynamic client used by the Petals SE Flowable through the Flowable's module 'flowable-cxf', specially JAXB dependencies (see PETALSDISTRIB-474).
  • Environment:
    -

Issue Links

Activity

Hide
Christophe DENEUX added a comment - Thu, 29 Apr 2021 - 16:03:56 +0200 - edited

The Petals Boostrap Launcher must create a dedicated URLClassloader from all Petals common dependencies as following:

Previous classloader hierarchy:

PlatformClassloader------------------
                                    |
                              AppClassloader
                          (loaded from MANIFEST
                       of petals-bootstrap-launcher
                         with common dependencies)
                                    |
              -----------------------------------------------
              |                                             |
        URLClassloader                          SharedLibrariesClassloader
(containing petals-default-launcher)                        |
              |                                             |
   PetalsContainerClassloader                      ComponentClassloader

New classloader hierarchy:

PlatformClassloader------------------
                                    |
                              AppClassloader
                        (empty, without extra JAR)
                                    |
                               URLClassloader                    <---------------- The new classloader layer
                    (created by petals-bootstrap-launcher,
                    and containing all common dependencies)
                                    |
              -----------------------------------------------
              |                                             |
        URLClassloader                          SharedLibrariesClassloader
(containing petals-default-launcher)                        |
              |                                             |
   PetalsContainerClassloader                      ComponentClassloader
Show
Christophe DENEUX added a comment - Thu, 29 Apr 2021 - 16:03:56 +0200 - edited The Petals Boostrap Launcher must create a dedicated URLClassloader from all Petals common dependencies as following: Previous classloader hierarchy:
PlatformClassloader------------------
                                    |
                              AppClassloader
                          (loaded from MANIFEST
                       of petals-bootstrap-launcher
                         with common dependencies)
                                    |
              -----------------------------------------------
              |                                             |
        URLClassloader                          SharedLibrariesClassloader
(containing petals-default-launcher)                        |
              |                                             |
   PetalsContainerClassloader                      ComponentClassloader
New classloader hierarchy:
PlatformClassloader------------------
                                    |
                              AppClassloader
                        (empty, without extra JAR)
                                    |
                               URLClassloader                    <---------------- The new classloader layer
                    (created by petals-bootstrap-launcher,
                    and containing all common dependencies)
                                    |
              -----------------------------------------------
              |                                             |
        URLClassloader                          SharedLibrariesClassloader
(containing petals-default-launcher)                        |
              |                                             |
   PetalsContainerClassloader                      ComponentClassloader
Hide
Christophe DENEUX added a comment - Tue, 23 Nov 2021 - 11:46:47 +0100

Fixed by svn#43779

Show
Christophe DENEUX added a comment - Tue, 23 Nov 2021 - 11:46:47 +0100 Fixed by svn#43779

People

Dates

  • Created:
    Thu, 29 Apr 2021 - 15:46:05 +0200
    Updated:
    Tue, 23 Nov 2021 - 11:46:47 +0100
    Resolved:
    Tue, 23 Nov 2021 - 11:46:47 +0100