Given three modules (sources at the end) where

  * "mod_A" exports its package "mtest1", to everyone
  * "mod_B" requires "mod_A" and exports its package "mtest2" to "mod_C"
  * "mod_C" requires "mod_B" and exports its package "mtest3" to everyone

"mod_B"'s class "mtest2.Class02A" defines two public fields, one static 
("pubStaticFromClass02A")
and one an instance ("pubFromClass02") one.

Compiling the modules and then using them in the following Java program (via 
the CLASSPATH) works,
here the source:

    TestUse_mtest3_Class03A.java

            public class TestUse_mtest3_Class03A
            {
                public static void main (String args[]) {
                    mtest3.Class03A o=new mtest3.Class03A();
                    System.out.println("o.pubStaticFromClass02A     : 
"+o.pubStaticFromClass02A );
                    System.out.println("o.pubFromClass02A           : 
"+o.pubFromClass02A     );
                    System.out.println("o: "+o+", o.getMyClassName(): 
"+o.getMyClassName());
                }
            }

Compiling the above program and running it yields:

    o.pubStaticFromClass02A     : static-mtest2.Class02A
    o.pubFromClass02A           : instance-mtest2.Class02A
    o: mtest3.Class03A@5afa04c, o.getMyClassName(): via: 
this=[mtest3.Class03A@5afa04c],
    getMyClassName()=[class-mtest1.Class01A]

Here is a 1:1 transcription from the above Java program to Rexx which uses Java 
reflection to
achieve the same:

    test.rex

            o=.bsf~new("mtest3.Class03A")          -- create Java object
            say "o~pubStaticFromClass01A:" o~pubStaticFromClass02A
            say "o~pubFromClass01A      :" o~pubFromClass02A
            say "o:" o "o~getMyClassName:" o~getMyClassName

            ::requires BSF.CLS   -- direct interpreter to load Java bridge

Running the Rexx program yields the following reflection error:

    // // -> -> RexxReflectJava9.processField(): EXCEPTION in GET-operation:
    tmpField="pubStaticFromClass02A" exception: 
"java.lang.IllegalAccessException: class
    org.rexxla.bsf.engines.rexx.RexxReflectJava9 cannot access class 
mtest2.Class02A (in module
    mod_B) because module mod_B does not export mtest2  to unnamed module 
@51c8530f"

The reflection code currently

  * gets the type from the Java object ("mtest3.Class03A") and tests whether 
the package "mtest3" is
    exported (it is),
  * looks for all declaredFields and finds none, so it gets the superclass 
"mtest2.Class02A",
  * looks for all declaredFields and locates the Field named 
"pubStaticFromClass02A" and invokes the
    Field's get method, supplying the Java object (an instance of class 
mtest3.Class03A) which
    causes an IlleagalAccessException.

Although it is true that "mod_B" is not exported to the unnamed module it is 
still the case that
"mod_C" is exported (and class "mtest3.Class03A" can be accessed), such that 
all public members in
its superclasses should be accessible via reflection, even in the case that a 
public member resides
in a module that is not exported to the reflector from the unnamed module?

The reflective code would be able to assess that the supplied object is from an 
exported type and
hence allow the get access in this case for reflected members in its 
superclasses, like it seems the
Java compiler allows for.

---rony

Here are the contents of the module directories in source:

    ---------------------------------------------------------------------------

    mod_A/module-info.java

            module mod_A { exports mtest1; }

    mod_A/mtest1/Class01A.java

            package mtest1;

            abstract public class Class01A
            {
                protected static String myClassName = "class-mtest1.Class01A";
            }

    ---------------------------------------------------------------------------

    mod_B/module-info.java

            module mod_B {
                requires mod_A;
                exports mtest2 to mod_C;
            }

    mod_B/mtest2/Class02A.java

            package mtest2;

            public class Class02A extends mtest1.Class01A
            {
                public static String 
pubStaticFromClass02A="static-mtest2.Class02A";
                public        String pubFromClass02A      
="instance-mtest2.Class02A";

                public String getMyClassName()
                {
                    return "via: this=["+this+"], 
getMyClassName()=["+myClassName+"]";
                }
            }

    ---------------------------------------------------------------------------

    mod_C/module-info.java

            module mod_B {
                requires mod_A;
                exports mtest2 to mod_C;
            }

    mod_C/mtest3/Class03A.java

            package mtest3;

            public class Class03A extends mtest2.Class02A
            {
            }

    --------------------------------------------------------------------------


Reply via email to