Rony G. Flatscher
2018-01-23 14:52:46 UTC
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: ***@5afa04c, o.getMyClassName(): via: this=[***@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
{
}
--------------------------------------------------------------------------
* "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: ***@5afa04c, o.getMyClassName(): via: this=[***@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
{
}
--------------------------------------------------------------------------