Task: load application classes using a custom class loader (CustomClassLoader
) in Java 8 style (without module-info.java
).
Project with three classes:
Main
- a class containing amain
method creating an instance of theCat
class and calling theCat::talk
method;Cat
- loadable class with thetalk
method, which prints the string "Meow" tostdout
;CustomClassLoader
- a class that is an implementation of a custom class loader.
To change the system loader to a custom CustomClassLoader
in documentation of the ClassLoader.getSystemClassLoader()
method it is written that for this it is necessary for the JVM to pass the name of the new system class loader through the argument java.system.class.loader
, and also to define a public constructor with a parameter of type ClassLoader
, which will be passed as AppClassLoader
when created.
Using classpath
:
java17 -Djava.system.class.loader=ru.ispras.j17.auto.onemodule.j8style.CustomClassLoader \
-cp . ru.ispras.j17.auto.onemodule.j8style.Main
or
java17 -Djava.system.class.loader=ru.ispras.j17.auto.onemodule.j8style.CustomClassLoader \
-jar java8style-1.0.jar
Output:
OpenJDK 64-Bit Server VM warning: Archived non-system classes are disabled because the java.system.class.loader property is specified (value = "ru.ispras.j17.auto.onemodule.j8style.CustomClassLoader"). To use archived non-system classes, this property must not be set
Main Class Module is unnamed module @2c7b84de
Cat Class Module is unnamed module @2c7b84de
System ClassLoader is ru.ispras.j17.auto.onemodule.j8style.CustomClassLoader@355da254
Main Class ClassLoader is ru.ispras.j17.auto.onemodule.j8style.CustomClassLoader@355da254
Cat Class ClassLoader is ru.ispras.j17.auto.onemodule.j8style.CustomClassLoader@355da254
Meow
Note:
OpenJDK 64-Bit Server VM warning
occurs because the system loader was replaced and, as a result, archiving of classes using the JVM was disabled. This is the so-called Class Data Sharing (CDS) optimization.
Using modulepath
:
java17 -Djava.system.class.loader=ru.ispras.j17.auto.onemodule.j8style.CustomClassLoader \
-p . -m java8style
Output:
Main Class Module is module java8style
Cat Class Module is module java8style
System ClassLoader is ru.ispras.j17.auto.onemodule.j8style.CustomClassLoader@4617c264
Main Class ClassLoader is jdk.internal.loader.ClassLoaders$AppClassLoader@28d93b30
Cat Class ClassLoader is jdk.internal.loader.ClassLoaders$AppClassLoader@28d93b30
Meow
- When a
CustomClassLoader
is created, its parent becomesjdk.internal.loader.ClassLoaders$AppClassLoader
; - Since
CustomClassLoader
is a system class loader, all classes to be loaded are first delegated to it, it loads application classes, and the rest is transferred tojdk.internal.loader.ClassLoaders$AppClassLoader
. - Both
Main
andCat
classes are loaded usingCustomClassLoader
in the case ofclasspath
, and are in the same unnamed module, which is bound to the loader. - However, if you run
java8style-1.0.jar
, then using the-p
and-m
options, all classes will be loaded intomodule java8style
, the system loader has changed, but the classesMain
andCat
are loaded usingAppClassLoader
. I have no answer to the question of why this happened, and my attempts to find out turned out to be a failure. I can only assume that this has something to do with the purpose of class loaders. In the Module API there is such an entity as a layer (ModuleLayer). The layer contains a map that assigns each module its loader, only this is a special type of loader calledpublic final class Loader extends SecureClassLoader
. Looking at the code of this class, you can see that this is an unusual class loader and it is closely related to the modular system, and operates on classes that are not available to us, and the class itself isfinal
. In connection with this assumption, it is not clear to me how you can write a custom loader that can do everything that theLoader
class can do in order to become its replacement.
- If you do not define a public constructor in
CustomClassLoader
, the JVM initialization error will occur:
Error occurred during initialization of VM
java.lang.Error: java.lang.NoSuchMethodException: ru.ispras.j8.auto.CustomClassLoader.<init>(java.lang.ClassLoader)
- Since the system class loader has been replaced with
CustomClassLoader
, the JVM now refuses to cache loaded classes in memory and issues a warning about this:
OpenJDK 64-Bit Server VM warning: Archived non-system classes are disabled because the java.system.class.loader property is specified (value = "com.habr.j8.auto.CustomClassLoader"). To use archived non-system classes, this property must not be set`.
There was a disabling of CDS (Class Data Sharing) optimization in the JVM.