There are several changes with regards to class loading, but so far we've only documented one.
A common requirement in server and testing frameworks is the isolation of external code from the framework.
Before Java 9, this could be done by loading the external code via a URLClassLoader
with a null
parent class loader, which limits it to just the classes of the runtime Java platform and the class path passed to the URLClassLoader
.
A null
parent class loader signifies the bootstrap class loader.
The set of classes that the bootstrap class loader is able to load has changed between Java 8 and Java 9:
- In Java 8, every platform class other than the JavaFX classes is visible to the bootstrap class loader.
- In Java 9, the bootstrap class loader is more restricted.
The list of modules that go into the bootstrap class loader can be found in JEP 261:
- java.base
- java.datatransfer
- java.desktop
- java.instrument
- java.logging
- java.management
- java.management.rmi
- java.naming
- java.prefs
- java.rmi
- java.security.sasl
- java.xml
- jdk.httpserver
- jdk.internal.vm.ci
- jdk.management
- jdk.management.agent
- jdk.naming.rmi
- jdk.net
- jdk.sctp
- jdk.unsupported
As a demonstration, BootstrapLoaderTest
attempts to load classes from several of the non-core java/javax packages to validate what packages are visible to the bootstrap class loader.
This shows the following packages that were visible under Java 8 to no longer be visible under Java 9:
java.sql.*
javax.activation.*
javax.annotation.*
javax.jws.*
javax.lang.model.*
javax.rmi.*
javax.script.*
javax.smartcardio.*
javax.sql.*
javax.tools.*
javax.transaction.xa.*
javax.xml.bind.*
javax.xml.crypto.*
javax.xml.soap.*
javax.xml.ws.*
NullParentClassLoaderIT
shows the consequences by trying to load a class from the project JAR that uses java.sql.Date
, which is among the invisible packages.
To observe that, you need to successfully build the JAR, either by building on Java 8 or running mvn package -DskipTests
on Java 9 (otherwise BootstrapLoaderTest
fails your build).
Either way, you can then run the test with mvn failsafe:integration-test
.
On Java 9, the new ClassLoader::getPlatformClassLoader, method must be used to obtain a parent that has visibility to all of the platform classes.
It can then be passed to the URLClassLoader
:
URL path[] = { ... };
ClassLoader parent = ClassLoader.getPlatformClassLoader();
URLClassLoader loader = new URLClassLoader(path, parent);
(Last checked: 8u152 and 9.0.1; contributed by Scott Stark)