p example (Re: Reflection: how can one access public fields (members) in a superclass ?
Rony G. Flatscher
Rony.Flatscher at wu.ac.at
Sat Jan 27 18:26:25 UTC 2018
On 24.01.2018 20:48, Alan Bateman wrote:
> On 24/01/2018 15:42, Rony G. Flatscher wrote:
>>
>> OK, now add to this the following class that uses p.C2 objects to access e.g. m() via it:
>>
>> G:\xfer\java9modules\03-20180124-AlanBatmanP\p>type UseC2.java
>>
>> public class UseC2
>> {
>> public static void main (String args[]) {
>> p.C2 o=new p.C2();
>> System.out.println("o="+o);
>> System.out.println("o.m()="+o.m());
>> }
>> }
>>
>> Compiling all three classes works.
>>
>> Running "UseC2" works and outputs:
>>
>> G:\xfer\java9modules\03-20180124-AlanBatmanP\p>java -cp ".;.." UseC2
>> o=p.C2 at 66048bfd
>> o.m()=-1
>>
>> So it is possible to access m() via the p.C2 object from UseC2.
> That's right and this is the reason for moving to the simpler example.
---
>
> To be absolutely sure then you should decompile C2.class to make sure that there isn't a bridge
> method calling C1's m2(). If you change m() to be final then that will keep the bridge method from
> complicating the picture.
>
> If you change UseC2 to use core reflection and you hit the issue because the Method object you get
> is p.C1.m(). Attempting to invoke this will fail with IllegalAccessException. In your other mail
> you show a code fragment where it catches exceptions and calls setAccessible - I'll guess that
> this may have been masking the issue in the Rexx bridge.
The logic to find a matching Method object is to start out in the object's class for which
reflective invocation is needed. Then using getDeclaredMethods() and look for the public method
(with the sought name and parameters types that can be used for the supplied arguments), if not
found, going up its superclass and repeating the process until a matching Method object is found.
Being sure that the found public Method object is the appropriate one setAccess() makes it accessible.
> For completeness then you may want to try out the new reflection API. I realize you have to
> compile to JDK 6 but I think you'll find it will work the same way as the invokevirtual that o.m()
> compiles to.
It will not be a problem to supply different reflection versions after the rewrite.
> MethodHandles.Lookup lookup = MethodHandles.lookup();
> MethodType mt = MethodType.methodType(int.class);
> MethodHandle mh = lookup.findVirtual(p.C2.class, "m", mt);
> Object res = mh.invoke(o);
Thank you very much for this snippet, it really helped me a lot to explore MethodHandles in the
context of my problem!
After some testing, it looks like it will allow me to solve the problem, although for a price
consisting of learning a totally different way (which is o.k. for me personally) of achieving what
used to be simple and safe (accessing only public members via reflection), but potentially also
incurring a performance penalty compared to using only reflection. The expected performance penalty
would be due to the fact that reflection cannot be by passed: the Rexx bridge supplies the member's
names usually in uppercase and primitive values as plain strings, such that one must use reflection
to locate candidate members (need to be public and caselessly carrying the Rexx supplied member
name), then check whether the Rexx supplied arguments can be coerced to the parameter types of the
candidate, and if so access it; if not, check the next candidate. Now, further steps will be
necessary in addition: among them create the MethodType, get the MethodHandle, render the arguments
and invoke it.
---
Is there a possibility to have invoke arguments to MethodHandles be relayed, say to some method
RexxValue2JavaValue, such that one can receive the MethodType, the Rexx arguments and return the
matching type-converted values that should then be used for the invoke operation?
---rony
More information about the jigsaw-dev
mailing list