Reflection: how does one access a protected member in a superclass reflectively?

Rony G. Flatscher Rony.Flatscher at wu.ac.at
Tue Jan 16 13:50:46 UTC 2018


On 16.01.2018 10:18, Alan Bateman wrote:
> On 15/01/2018 20:56, Rony G. Flatscher wrote:
>> :
>>
>> So the question is, how can I reflectively access "mtest1.Class01A" static protected field
>> "myClassName" from "mtest3.Class03a" in Java 9?
>>
> The scenario in your mail is complicated but if I read it correctly then I would expect this code
> in mtest3.Class03A (mod_C) to work:
> Class.forName("mtest1.Class01A").getDeclaredField("myClassName").get(null);
The problem here is, that no code from any of the modules is doing the reflection. Rather the
reflection comes from packages on the class path, hence from the unnamed module.

> I can't tell if the code in the unnamed module extends mtest1.Class01A or not. If it does then the
> same code should work, if it's not a sub-class then you should see IllegalAccessException being
> thrown.
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",
          + 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!

  * "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";

      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"

          + 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"

> Your traces show InaccessibleObjectException being thrown so I think you are attempting to call
> setAccessible(true) to suppress the access check. You can't do on that protected members when the
> package is not open for deep reflection. In the example, mod_A would need to `opens mtest1` to
> allow this. 
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".

This is a very basic and important property of the Java language.

Therefore I assume that this is a bug in the current implementation of Java 9, but want to know for
sure.

---

I asked this very question ("are protected members in superclasses regarded to be public for
subclasses") almost nine months ago and it was agreed that "protected" in superclasses become
effectively "public" for subclasses in Java 9 as well, so it was clear that when adjusting the
bridge to Java 9 everything would work as in the past for the users. [For the past 17 years I have
always adhered to these Java semantics in the Rexx/ooRexx-Java bridge, users of the bridge have only
been able to access public classes and public members and protected classes and protected members of
superclasses. There has never been a need for any deep reflection (nor "desire" to do so) as package
private and private members have to be respected to be "private".]

---rony




More information about the jigsaw-dev mailing list