I am using Netbeans 12.5 and java 16
In an Java Modular Project I have 2 Modules
Modular-Testing(/*The Project Name*/)
|
|----Consumer(/*Module Name*/)
| |
|--classes(/*Folder Name*/)
|
|--main(/*package name*/)
|
|--CustomModuleTest.java(Main Class)
|--Test_Module_A(/*Module Name*/)
|
|--classes(/*Folder Name*/)
|
|--package_a(/*package name*/)
|
|--ClassA.java
CustomModuleTest.java
public static void main(String[] args)throws Exception
{
Path baseDir=Path.of("C:/Users/Home/Documents/NetBeansProjects/Netbeans/Modular-Testing/build/modules/");
//Create the configuration for these two modules with boot-layer configuration as it's parent
Configuration level1=Configuration.resolve
(
ModuleFinder.of(baseDir.resolve("Consumer"),baseDir.resolve("Test_Module_A"))
,List.of(ModuleLayer.boot().configuration())
,ModuleFinder.of()
,List.of("Consumer","Test_Module_A")
);
//create the module layer with only one system class loader and boot layer as parent
ModuleLayer.Controller layer1=ModuleLayer.defineModulesWithOneLoader
(
level1
,List.of(ModuleLayer.boot())
,ClassLoader.getSystemClassLoader()
);
//this is the main purpose of this test. I want to call ClassA.callMe() via reflection after I have dynamically achieved the permissions for it by first
//Making Consumer Module read(requires) Test_Module_A
//Making Test_Module_A open it's package(package_a) to Consumer
//With this consumer should have full reflective access to Test_Module_A(or that's what i had hoped but it didn't work)
//Require(Read)
//Make Module Consumer--------------->Test_Module_A
layer1.addReads
(
layer1.layer().findModule("Consumer").get()
,layer1.layer().findModule("Test_Module_A").get()
);
//Open package_a
//Make Module Test_Module_A-------------------->Consumer
layer1.addOpens
(
layer1.layer().findModule("Test_Module_A").get()
,"package_a"
,layer1.layer().findModule("Consumer").get()
);
//Do the actual Test
Class targetClass=layer1.layer().findLoader("Test_Module_A").loadClass("package_a.ClassA");
Method method=targetClass.getDeclaredMethod("callMe");
method.trySetAccessible();
method.invoke(null); //<---------Crashes Here(It's a static method so no object reference)
}
ClassA does nothing
package package_a;
public class ClassA
{
private static void callMe()
{
System.out.println("Hooray You Called Me Using ModuleLayers!!!");
}
}
module-info for both Consumer & Test_Module_A are empty
module Consumer{}
module Test_Module_A{}
the module-info of both these modules are empty because i want to dynamically add Opens/Exports using ModuleLayer.Controller
The class is located with no problems the method is made accessable using trySetAccessible() but as soon as i call invoke i get this error
Exception in thread "main" java.lang.IllegalAccessException: class main.CustomModuleTest (in module Consumer) cannot access class package_a.ClassA (in module Test_Module_A) because module Test_Module_A does not export package_a to module Consumer
at java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:385)
at java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:687)
at java.base/java.lang.reflect.Method.invoke(Method.java:559)
The test is run from CustomModuleTest.java main method inside Consumer Module the addReads & addOpens method either don't work or i am just using it wrong
Any ideas?
You are creating a new module layer containing two modules and establishing access of one of these modules to the other. However, you actually want to establishing access for the currently running main method to one the these modules.
The currently running main method can’t be part of the new module layer it just creates. Assuming standard launcher setup, it belongs to a Controller
module loaded by the system class loader as part of the boot-layer.
So, instead of granting access to a new module of the same name in the new layer, you have to change the code to grant access to the already loaded Controller
module. Since the new Controller
module of the new module layer serves no purpose then, you can remove it from the layer configuration.
public static void main(String[] args) throws Exception {
Path baseDir = Path.of(
"C:/Users/Home/Documents/NetBeansProjects/Netbeans/Modular-Testing/build/modules/");
// Create the configuration for the new module
// with boot-layer configuration as it's parent
Configuration level1=Configuration.resolve
(
ModuleFinder.of(baseDir.resolve("Test_Module_A")),
List.of(ModuleLayer.boot().configuration()),
ModuleFinder.of(), List.of("Test_Module_A")
);
//create the module layer with only one class loader and boot layer as parent
var layer1Controller = ModuleLayer.defineModulesWithOneLoader(
level1, List.of(ModuleLayer.boot()), ClassLoader.getSystemClassLoader()
);
var testModA = layer1Controller.layer().findModule("Test_Module_A").get();
var myModule = CustomModuleTest.class.getModule();
myModule.addReads(testModA); // add read edge
layer1Controller.addOpens(testModA, "package_a", myModule); // open package_a
//Do the actual Test
Class<?> targetClass = testModA.getClassLoader().loadClass("package_a.ClassA");
Method method = targetClass.getDeclaredMethod("callMe");
method.setAccessible(true);
method.invoke(null);
}