On 16.01.2018 16:03, Alan Bateman wrote: > On 16/01/2018 13:50, Rony G. Flatscher wrote: >> The excercise here is as follows: >> >> * there are classes in "mod_A" which get extended in "mod_B" and once more >> extended in "mod_C". >> * Hence "mod_B" requires "mod_A", and "mod_C" requires "mod_B", where >> "mod_B" exports to >> "mod_C" only >> * These are the two chains of class extensions, one (mtest1.Class01A) >> defines an abstract >> public class with protected members, one (mtest1.Class01B) defines a >> public class with public >> members, hence: >> o one chain is: >> + in "mod_A" there is the class "abstract public class >> mtest1.Class01A", which contains >> a protected static field named "myClassName", >> + in "mod_B" there is the class "public class Class02A extends >> mtest1.Class01A", has no >> static field named "myClassName", >> + in "mod_C" there is the class "publi class Class03A extends >> mtest2.Class02A", has no >> static field named "myClassName. >> o another chain is: >> + in "mod_A" there is the class "abstract public class >> mtest1.Class01B", which contains >> a protected static field named "myClassName", >> > If I read the earlier text correctly then Class01B.myClassName is public. Yes.
> >> + in "mod_B" there is the class "public class Class02B extends >> mtest1.Class01B", has no >> static field named "myClassName", >> + in "mod_C" there is the class "public class Class03B extends >> mtest2.Class02B", has no >> static field named "myClassName. >> >> Two scenarios, one works, one causes the "IllegalAccessException": >> >> * works: creating an instance of "mtest3.Class03B" reflectively and then >> getting the value of >> the public static field "myClassName" in "mtest1.Class01B", works >> reflectively! >> > I assume the caller is org.rexxla.bsf.engines.rexx.RexxReflectJava9 on the > class path. Module > mod_A exports mtest1, mtest1.Class1B is public, code on the class path can > reflect on Class1B's > public members. > > >> * "IllegalAccessException": creating an instance of "mtest3.Class03A" >> reflectively and then >> getting the value of the public static field "myClassName" in >> "mtest1.Class01A", causes the >> "IllegalAccessException"; >> > I think you mean "protected static". Yes, sorry. > >> * >> >> >> >> o Interestingly, >> + the first error message is: "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" >> > This looks correct, RexxReflectJava9 is not a sub-class of mtest1.Class01A so > it can't expect to > reflect on Class01A's protected members. > > >> + in the catch block then trying a "setAccessible(true)" yields >> another >> "IllegalAccessException" now with the following error message: >> "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 @33b37288" >> > The InaccessibleObjectException looks correct too. > > >> And that is exactly the point. "mtest1.Class01A" is a superclass of >> "mtest3.Class03A". Therefore >> the protected members in the superclass "mtest1.Class01A" are public for its >> subclasses like >> "mtest3.Class03A". > Do you have an issue here? If code is added to mod_C/mtest3.Class03A to > reflect on protected > members of mod_A/mtest1.Class01A then I would expect it to work. Furthermore, > I would expect > setAccessible(true) to succeed on protected static members too (not instance > members of course). > > That said, the scenario that you've shown is code in RexxReflectJava9 doing > the reflection. It's > not in a sub-class of mtest1.Class01A so it should not have any access to its > protected members. Well that is probably the core of the problem: who needs to be the subclass, the reflector or the object to be reflected upon (whose inheritance tree is being walked up towards the root class, and if public or protected members are found reflectively accessed)? Or conceptually: the "mtest3.Class03A object" is clearly from a subclass of "mtest1.Class01A". Why should it then not be allowed to access the public and protected members in the superclass "mtest1.Class01A" via reflection on behalf of the "mtest3.Class03A object", which gets supplied in the reflective access and which can be used to check whether the access would be legal or not? ---rony