On 17.01.2018 14:12, Alan Bateman wrote:
> On 17/01/2018 12:18, Rony G. Flatscher wrote:
>> :
>>
>> The reflection logic in the bridge is (simplified) as follows:
>>
>>   * use the object's 'o' class and look up its declared methods or fields, 
>> analyze further, if
>>     member is 'public', otherwise
>>
>>       o iterate over all of its superclasses looking up in each class all 
>> declared methods or
>>         fields, analyze further, if member is 'public' *or* 'protected' 
>> (looking up a superclass
>>         'protected' is regarded to be 'public' for the subclass) and, if a 
>> matching member is
>>         found, carry out the operation (in this case a Field.get()) and 
>> return its value
>>
>> This way it is assured that the users of the bridge are never able to get at 
>> private or package
>> private members (nor that they are able to invoke a protected member in the 
>> object's type itself).
>>
> Accessibility has been significantly upgraded in Java SE 9. "public" used to 
> imply accessible to
> everyone, now we have "public to everyone", "public to friend modules" or 
> "public within a
> module".  If you want the above logic to work with modules then it will need 
> to be updated to
> handle classes in named modules. It will essentially amount to overhauling 
> the above to find the
> accessible members rather the public members (in public classes).
Would you have concrete suggestions for this use-case, i.e. a framework that is 
not part of a
module, but having a need to access public types from exported packages and get 
reflective access to
objects supertype's protected members?

This actually is an urgent need for my bridge. The BSF4ooRexx package comes 
with a wealth of samples
to show ooRexx programmers how easy it is to use Java as a huge external ooRexx 
class library. Some
of these samples in Java 9 now cause warnings, e.g. one example:

    ... cut ...
    WARNING: An illegal reflective access operation has occurred
    WARNING: Illegal reflective access by 
org.rexxla.bsf.engines.rexx.RexxAndJava
    
(file:/C:/Program%20Files%20(x86)/BSF4ooRexx/bsf4ooRexx-v600-20180101-bin.jar)

    to method 
sun.java2d.SunGraphics2D.setRenderingHint(java.awt.RenderingHints$Key,java.lang.Object)

    WARNING: Please consider reporting this to the maintainers of
    org.rexxla.bsf.engines.rexx.RexxAndJava
    WARNING: Use --illegal-access=warn to enable warnings of further illegal 
reflective access
    operations
    WARNING: All illegal access operations will be denied in a future release
    ... cut ...

So all of a sudden the reflection does not work anymore. The reason being that 
the graphic "g"
context in javax.swing.JComponent's paintComponent (java.awt.Graphics g) is 
actually a
"sun.java2d.SunGraphics2D" object, that according to this Java 9 warning is not 
exported and will be
an error in Java 10. (I have assumed, that if I would use a reflection Method 
object from
javax.swing.JComponent (which is protected and can only be accessed by ooRexx, 
if a dynamically
created subclass of JComponent is created from which the work is done) for 
setRenderingHint() that
invoking the Method object with the Sun object would succeed.)

There are other use-cases where such warnings occur.

No user of the ooRexx-Java bridge knows anything of the new module system in 
Java 9, nor should she
have a need to know if these sample programs have worked flawlessly in the 
past. Therefore I am
seriously interested to find a solution that adheres to the Java 9 module 
system.

> BTW: On protected members then I assume they have never been accessible to 
> the bridge, maybe the
> bridge is using setAccessible to suppress the access checks for those cases?
Yes.
(Have been hoping that that need would be forgone eventually, when that 
reflection area gets
reworked, updated for this protected member case, if the object to be worked on 
stems from a
subclass to allow exactly the same thing the Java compiler has allowed for, 
this time for an
interpreted language.)

>
>>
>> ---
>>
>> The current implementation seems to do the following: it checks whether a 
>> class is from an 
>> exported package, if not it creates an exception. If the class is exported 
>> it then checks whether
>> the reflected member is public, if not it creates an exception.
>>
>> What I would have expected is this: everything like the current 
>> implementation, but in the second
>> step, if the member is not public, check whether the object's class for 
>> which the reflection
>> takes place is a subclass of the class that is being checked and if so, 
>> allow protected members
>> to be accessed as well. Hence: in the example presented, the packages 
>> 'mtest1' and 'mtest3' are
>> exported, the class 'mtest3.Class03A' extends 'mtest2.Class02A' which 
>> extends 'mtest1.Class01A'.
>> Therefore the object of type 'mtest3.Class03A' is a subclass of 
>> 'mtest1.Class01A', hence as
>> 'mtest1' is exported all 'mtest1.Class01A' public *and* protected members 
>> should be accessible to
>> the object of the subtype 'mtest3.Class03A' via reflection in Java 9 as well.
> You should find that the protected members are accessible in the sub-class 
> (mtest3.Class03A in
> this case). They won't be accessible to the bridge code of course (as least 
> not without some kind
> of rights delegation as John mentioned).

Not with Java 9 javac, the following Java program:

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

yields the error message:

    
F:\work\svn\bsf4oorexx\trunk\bsf4oorexx.dev\testUnits\bsf4rexx\java9modules>java
  -cp
    ".;F:\work\svn\bsf4oorexx\trunk;.;C:\Program Files
    (x86)\BSF4ooRexx\bsf4ooRexx-v600-20180101-bin.jar;C:\Program Files
    (x86)\BSF4ooRexx\jni4net.j-0.8.8.0.jar;C:\Program Files 
(x86)\BSF4ooRexx\oorexx.net.jar;."
    --module-path out --add-modules mod_A,mod_B,mod_C TestUse
    Exception in thread "main" java.lang.IllegalAccessError: tried to access 
field
    mtest1.Class01A.myClassName from class TestUse
            at TestUse.main(TestUse.java:5)

Note: the TestUse class will be part of the unnamed module.

---

Ad "rights delegation mechanism": would that really allow the bridge from the 
unnamed module to do
what is needed and therefore sought, ie. accessing protected members in 
exported superclasses? If
so, how? Would you have any links for further reading?

If you could tell me that I misunderstood the access rules of the 
java.lang.invoke package and that
it was possible to use it and/or the jdk.dynalink package to overcome, I would 
definitely try to
apply that to solve this issue, as this is really very important for the users 
of the bridge for
whom it is simply impossible to solve this.

---

Alternatively: what is the problem that you see for the Java 9 module system, 
if access checking is
done with the extension of also allowing protected members to be used, if the 
object on which the
reflective access is to be carried out is indeed from a subclass of the 
defining class of the
java.lang.reflect object being supplied?

---rony


Reply via email to