Finally having gained enough time to start rewriting the reflection part for a bridge between a scripting language (ooRexx) and Java 9.
>From past discussions on this list my view upon accessing members in >superclasses that are protected in Java 9 is possible as such protected members are regarded to be public (they are accessible) from their subclasses. To test against the new module system I have created three simple modules (only what is relevant to this problem is given): * "mod_A": defines a package "mtest1" with an abstract public class "Class01A" that implements an interface "I01A", its "module-info.java" reads: "module mod_A { exports mtest1; }" * "mod_B": defines a package "mtest2" with a public "Class02A" which extends "mtest1.Class01A" and implements an interface "I02A" which extends "mtest1.I01A", its "module-info.java" reads: "module mod_B { requires mod_A; exports mtest2 to mod_C; } * "mod_C": defines a package "mtest2" with a public "Class03A" which extends "mtest2.Class02A", its "module-info.java" reads: "module mod_C { exports mtest3; requires mod_B; }" The code doing the reflection resides in the unnamed module for the time being (it eventually will be part of a module). Running the script code is done against the following Java settings: -cp "%CLASSPATH%" --module-path F:\java9modules\out --add-modules mod_A,mod_B,mod_C In the first round reflecting Fields is used as a testbed. The reflection code at this stage is able to successfully skip over the closed "mod_B" module and arrive at "mod_A" classes. However, reflecting for "Class03A" instance is not able to access the defined *protected* static field "myClassName" in the superclass "Class01A" (the String value of that static field is: "class-mtest1.Class01A")! The debug output with the trailing stack trace for the runtime error is: about to load class [mtest3.Class03A] loaded, clz~toString: [class mtest3.Class03A] [java.lang.Class@4973813a] package: [package mtest3] module: [module mod_C] org.rexxla.bsf.engines.rexx.RexxReflectJava9@6fb0d3ed -> reflect(rru): org.rexxla.bsf.engines.rexx.RexxReflectUtil@16f7c8c1, field values: ---> rajo =[org.rexxla.bsf.engines.rexx.RexxAndJava@24a35978] invocationType=[GET_FIELD_VALUE] reflectionType=[REFLECT_FIELD] bStrict =[false] beanName =[mtest3.Class03A@1563da5] bean =[mtest3.Class03A@1563da5] instanceof Class? [false] beanClz =[class mtest3.Class03A] memberName =[MYCLASSNAME] rexxArgs[] =[[Ljava.lang.String;@df27fae], rexxArgs.length =[3]: [GETFIELDVALUE, mtest3.Class03A@1563da5, MYCLASSNAME] tmpRexxArgs[] =[[Ljava.lang.String;@704921a5], tmpRexxArgs.length=[0]: [] funcArgs[] =[[Ljava.lang.Object;@727803de], funcArgs.length =[0]: [] bReturnJSO =[false] bTryCoercions =[true] <--- \\// RexxReflectJava9.reflectField: (1) in tmpClz.getSuperclass() loop: tmpClz=[mtest2.Class02A], BEFORE isExported() \\// RexxReflectJava9.reflectField: package of tmpClz not EXPORTED, hence SKIPPING tmpClz: [mtest2.Class02A] \\// RexxReflectJava9.reflectField: now checking ---> tmpClz=[mtest1.Class01A] \\// RexxReflectJava9.reflectField: (1) in tmpClz.getSuperclass() loop: tmpClz=[mtest1.Class01A], BEFORE isExported() //\\ RexxReflectJava9.reflectField: (2) in tmpClz.getSuperclass() loop: tmpClz=[mtest1.Class01A], AFTER isExported() RexxReflectJava9.processField(), arrived: -> [GET_FIELD_VALUE], tmpField=[protected static java.lang.String mtest1.Class01A.myClassName]: field=[MYCLASSNAME] in object=[mtest3.Class03A@1563da5] RexxReflectJava9.processField(): => [GET_FIELD_VALUE]: found field=[MYCLASSNAME] in object=[mtest3.Class03A@1563da5/mtest3.Class03A@1563da5] oops GET-operation: tmpField "myClassName" caused exception "java.lang.IllegalAccessException: class org.rexxla.bsf.engines.rexx.RexxReflectJava9 cannot access a member of class mtest1.Class01A (in module mod_A) with modifiers "protected static"" java.lang.reflect.InaccessibleObjectException: Unable to make field protected static java.lang.String mtest1.Class01A.myClassName accessible: module mod_A does not "opens mtest1" to unnamed module @16022d9d at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(Unknown Source) at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(Unknown Source) at java.base/java.lang.reflect.Field.checkCanSetAccessible(Unknown Source) at java.base/java.lang.reflect.Field.setAccessible(Unknown Source) at org.rexxla.bsf.engines.rexx.RexxReflectJava9.processField(RexxReflectJava9.java:294) at org.rexxla.bsf.engines.rexx.RexxReflectJava9.reflectField(RexxReflectJava9.java:113) at org.rexxla.bsf.engines.rexx.RexxReflectJava9.reflect(RexxReflectJava9.java:59) at org.rexxla.bsf.engines.rexx.RexxAndJava.javaCallBSF(RexxAndJava.java:3247) at org.rexxla.bsf.engines.rexx.RexxAndJava.javaCallBSF(RexxAndJava.java:4163) at org.rexxla.bsf.engines.rexx.RexxAndJava.jniRexxRunProgram(Native Method) at org.rexxla.bsf.engines.rexx.RexxEngine.apply(RexxEngine.java:1153) at org.rexxla.bsf.RexxDispatcher.main(RexxDispatcher.java:158) Doing the comparable operation - accessing a field named "myClassName" in Java code from "mtest3.Class03a" (in the main method) succeeds! Here is the output of running "mtest3.Class3A" for comparison: F:\java9modules>java --module-path out -m mod_C/mtest3.Class03A class mtest3.Class03A.main() ... getMyClassNameStatic()=[class-mtest1.Class01A] myClassName =[class-mtest1.Class01A] getMyName1() =[from Class01A (static)] o.getMyName2() =[from Class02A (instance)] o.myClassName =[class-mtest1.Class01A] So the question is, how can I reflectively access "mtest1.Class01A" static protected field "myClassName" from "mtest3.Class03a" in Java 9? The Java code for "mtest1.Class01A" (in "mod_A"), "mtest2.Class02A" (in "mod_B") and "mtest3.Class03A" (in "mod_C") is given below. ---rony "mod_A": package mtest1; abstract public class Class01A implements I01A { protected static String myClassName = "class-mtest1.Class01A"; protected static String myName1 = "from Class01A (static)"; protected String myName2 = "from Class01A (instance)"; public static void main (String args[]) { System.err.println(Class01A.class+".main() ..."); } public static String getMyClassNameStatic() // static method in interface { return myClassName; } abstract public String getMyClassName() ; // default method in interface static protected String getMyName1() { return myName1; } abstract protected String getMyName2(); } "mod_B": package mtest2; public class Class02A extends mtest1.Class01A implements I02A { public static String myName1 = "from Class02A (static)"; public String myName2 = "from Class02A (instance)"; public static void main (String args[]) { System.err.println(Class02A.class+".main() ..."); System.err.println(" getMyClassNameStatic()=["+ getMyClassNameStatic()+"]"); System.err.println(" getMyName1() =["+ getMyName1() +"]"); Class02A o=new Class02A(); System.err.println(" o.getMyName2() =["+o.getMyName2() +"]"); System.err.println(" o.getMyClassName() =["+o.getMyClassName() +"]"); } public String getMyClassName() { return myClassName; } protected String getMyName2() { return myName2; } } "mod_C": package mtest3; public class Class03A extends mtest2.Class02A { public static void main (String args[]) { System.err.println(Class03A.class+".main() ..."); System.err.println(" getMyClassNameStatic()=["+ getMyClassNameStatic()+"]"); System.err.println(" myClassName =["+ myClassName +"]"); System.err.println(" getMyName1() =["+ getMyName1() +"]"); Class03A o=new Class03A(); System.err.println(" o.getMyName2() =["+o.getMyName2() +"]"); System.err.println(" o.myClassName =["+o.myClassName +"]"); } } for completeness the Interface classes: "mod_A": package mtest1; public interface I01A { static public String getMyClassNameStatic() // static method in interface { System.err.println("\t<<<(static public getMyClassNameStatic() method from ["+mtest1.I01A.class+"])>>>"); return "interface-mtest1.I01A"; // myClassName; } default public String getMyClassName() // default method in interface { System.err.println("\t<<<(default public getMyClassName() method from ["+mtest1.I01A.class+"])>>>"); return "interface-mtest1.I01A"; // myClassName; } } "mod_B": package mtest2; public interface I02A extends mtest1.I01A { static public String getMyClassNameStatic() // static method in interface { System.err.println("\t<<<(static public getMyClassNameStatic() method from ["+mtest2.I02A.class+"])>>>"); return "interface-mtest2.I02A"; // myClassName; } default public String getMyClassName() // default method in interface { System.err.println("\t<<<(default public getMyClassName() method from ["+mtest2.I02A.class+"])>>>"); return "interface-mtest2.I02A"; // myClassName; } }