Task: load any application class using a custom class loader (CustomClassLoader) from another module (the modules are NOT linked through module-info.java).
Modules (declared via module-info.java):
manual.fewmodules.separately.nodeps.loading:Main- a class containing themainmethod, where an instance of theCustomClassLoaderclass is created, theCatclass is loaded using it, creating an instance of the classCatand calling theCat::talkmethod;CustomClassLoader- a class that is an implementation of a custom class loader;
manual.fewmodules.separately.nodeps.loadable:Cat- loadable class with thetalkmethod, which prints the string "Meow" tostdout.
Using modulepath:
java17 -p loading-1.0.jar -m manual.fewmodules.separately.nodeps.loadingOutput:
[loading] Main Class Module is module manual.fewmodules.separately.nodeps.loading
[loading] Main Class ClassLoader is jdk.internal.loader.ClassLoaders$AppClassLoader@4554617c
ClassLoader for [loadable] module is jdk.internal.loader.Loader@4a574795
[loadable] Main Class ClassLoader is jdk.internal.loader.Loader@4a574795
[loadable] Cat Class ClassLoader is jdk.internal.loader.Loader@4a574795
[loadable] Main Class Module is module manual.fewmodules.separately.nodeps.loadable
[loadable] Cat Class Module is module manual.fewmodules.separately.nodeps.loadable
MeowThe class modules are as we wanted, but the Cat class loader turned out to be not CustomClassLoader as we expected, but some Loader. The fact is that in the defineModuleWithOneLoader method, a new Loader loader is created (the same one that I mentioned in the Java 8: Auto Loading example), the parent of which becomes the passed CustomClassLoader.
private static ModuleLayer createLayer(Path modulePath, String moduleName) {
/* ... */
return bootLayer.defineModulesWithOneLoader(config, new CustomClassLoader());
}Indeed, in documentation so and it is written:
public ModuleLayer defineModulesWithOneLoader(Configuration cf, ClassLoader parentLoader)
parentLoader- The parent class loader for the class loader created by this method; may benullfor the bootstrap class loader.
Thus, we do not have the opportunity to somehow pass our own class loader to the layer; we can only indicate the parent for the newly created one. Moreover, according to the same documentation, class loading will be delegated to the parent only if Loader does not find the package in which the class is located, here you can come up with different hacks based on this delegation model.
- You can rewrite the code a little and add a hack that will force
Loaderto delegate class loading to a custom class loader: Java 17. Manual Loading (loading and loadable) - hack
.jpg)