I'm playing around with the new modular system, and am running into a problem with reflection.
Somewhere in my code, I try to call the method getValue of a Map.Entry via reflection. It doesn't let me do it.
I have read a few tutorials about the new modular system, why protections against reflection ahve been set up, what are exports and opens, how and where to declare them and so on. But for this particular one I'm not sure to understand everything.
Here's the minimal code I'm able to come with:
package pkg;
import java.util.*;
import java.lang.reflect.*;
public class Test {
public static void main (String[] args) throws Exception {
Map<String,Object> someMap = new LinkedHashMap<>();
someMap.put("someKey", "someValue");
Map.Entry<String,Object> entry = someMap.entrySet().iterator().next();
System.out.println(entry.getValue()); // normal access is fine
Method getter = entry .getClass() .getMethod("getValue");
getter.setAccessible(true); //1
System.out.println(getter.invoke(entry)); //2
}}
When calling setAccessible, it crashes on it (1) :
Exception in thread "main" java.lang.reflect.InaccessibleObjectException: Unable to make public final java.lang.Object java.util.HashMap$Node.getValue() accessible: module java.base does not "opens java.util" to module mymodule
When commenting the setAccessible (1), it crashes when calling invoke (2) :
Exception in thread "main" java.lang.IllegalAccessException: class pkg.Test (in module mymodule) cannot access a member of class java.util.HashMap$Node (in module java.base) with modifiers "public final"
Fortunately, error messages are quite explicit: I can solve the problem by using the command-line argument --add-opens java.base/java.util=mymodule
, to add the missing open.
But it's probably not the correct way to go long term.
I have read somewhere that --add-opens/exports are going to disappear with Java 11 anyway.
Isn't there a better solution than using --add-opens ?
Normal/direct/regular access works, Method getValue is public, Map.Entry is obviously correctly exported from java.base. So why is this reflection call blocked ?
Thank you for your answers.