|
| 1 | +## Java 17. Manual Loading (loading and loadable) |
| 2 | +--- |
| 3 | +**Task:** load any application class using a custom class loader (`CustomClassLoader`) from another module (the modules are NOT linked through `module-info.java`). |
| 4 | + |
| 5 | +### Solution |
| 6 | +--- |
| 7 | +Modules (declared via `module-info.java`): |
| 8 | +- `manual.fewmodules.separately.nodeps.loading`: |
| 9 | + - [`Main`](loading/src/ru/ispras/j17/manual/fewmodules/separately/withdeps/loading/Main.java) - a class containing the `main` method, where an instance of the `CustomClassLoader` class is created, the `Cat` class is loaded using it, creating an instance of the class `Cat` and calling the `Cat::talk` method; |
| 10 | + - [`CustomClassLoader`](loading/src/ru/ispras/j17/manual/fewmodules/separately/withdeps/loading/CustomClassLoader.java) - a class that is an implementation of a custom class loader; |
| 11 | +- `manual.fewmodules.separately.nodeps.loadable`: |
| 12 | + - [`Cat`](loadable/src/ru/ispras/j17/manual/fewmodules/separately/withdeps/loadable/Cat.java) - loadable class with the `talk` method, which prints the string *"Meow"* to `stdout`. |
| 13 | + |
| 14 | +### Run |
| 15 | +--- |
| 16 | +Using `modulepath`: |
| 17 | + |
| 18 | +```shell |
| 19 | +java17 -p loading-1.0.jar -m manual.fewmodules.separately.nodeps.loading |
| 20 | +``` |
| 21 | + |
| 22 | +Output: |
| 23 | + |
| 24 | +```shell |
| 25 | +[loading] Main Class Module is module manual.fewmodules.separately.nodeps.loading |
| 26 | +[loading] Main Class ClassLoader is jdk.internal.loader.ClassLoaders$AppClassLoader@4554617c |
| 27 | +ClassLoader for [loadable] module is jdk.internal.loader.Loader@4a574795 |
| 28 | +[loadable] Main Class ClassLoader is jdk.internal.loader.Loader@4a574795 |
| 29 | +[loadable] Cat Class ClassLoader is jdk.internal.loader.Loader@4a574795 |
| 30 | +[loadable] Main Class Module is module manual.fewmodules.separately.nodeps.loadable |
| 31 | +[loadable] Cat Class Module is module manual.fewmodules.separately.nodeps.loadable |
| 32 | +Meow |
| 33 | +``` |
| 34 | + |
| 35 | +### Explanation |
| 36 | +--- |
| 37 | +.jpg) |
| 38 | + |
| 39 | +The 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`. |
| 40 | + |
| 41 | +```java |
| 42 | +private static ModuleLayer createLayer(Path modulePath, String moduleName) { |
| 43 | + /* ... */ |
| 44 | + return bootLayer.defineModulesWithOneLoader(config, new CustomClassLoader()); |
| 45 | +} |
| 46 | +``` |
| 47 | + |
| 48 | +Indeed, in [documentation](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/ModuleLayer.html#defineModulesWithOneLoader(java.lang.module.Configuration,java.util.List,java.lang.ClassLoader):~:text=of%20parent%20layers%20in%20search%20order-,parentLoader,-%2D%20The%20parent%20class%20loader%20for%20the) so and it is written: |
| 49 | + |
| 50 | +```java |
| 51 | +public ModuleLayer defineModulesWithOneLoader(Configuration cf, ClassLoader parentLoader) |
| 52 | +``` |
| 53 | + |
| 54 | +> `parentLoader` - The parent class loader for the class loader created by this method; may be `null` for the |
| 55 | +> bootstrap class loader. |
| 56 | +
|
| 57 | +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. |
| 58 | + |
| 59 | +### Notes |
| 60 | +--- |
| 61 | +- You can rewrite the code a little and add a hack that will force `Loader` to delegate class loading to a custom class loader: [Java 17. Manual Loading (loading and loadable) - hack](https://github.com/temikfart/java-classloading/tree/main/java-17/manual/few-modules/separately/no-deps-hack) |
0 commit comments