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.


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

 *


      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.

-Alan

Reply via email to