On 16.01.2018 20:38, John Rose wrote: > On Jan 16, 2018, at 10:37 AM, Rony G. Flatscher <rony.flatsc...@wu.ac.at > <mailto:rony.flatsc...@wu.ac.at>> wrote: >> >> Well that is probably the core of the problem: who needs to be the subclass, >> the reflector or the >> object to be reflected upon (whose inheritance tree is being walked up >> towards the root class, and >> if public or protected members are found reflectively accessed)? > > Quick comment: > > With the core reflection API, the reflector's permissions > are derived from the reflector, not the class being investigated. > > This works fine when a class reflects itself but is not so good for > frameworks. > > The reflection API in java.lang.invoke, though more limited, does > support rights delegation through the Lookup object. This means > that your "patient" class doesn't need to do the reflection work; > it can merely create a private lookup in itself and hand it to the > framework, which can do the reflection on behalf of the patient. > > You can even mix the old and new mechanisms (a point I don't > think I've seen on this thread, although I haven't read it all). > Given a private lookup object in some patient P, a framework > class F can create a method handle on a core reflection API > point that is @CallerSensitive (like Class.forName, etc. etc.) > which allows F to call that API point with the same rights as > P, not F. Thank you for the pointer, reading through <https://docs.oracle.com/javase/9/docs/api/java/lang/invoke/MethodHandles.Lookup.html> it seems that the access problem cannot be solved with that package either.
The problem at hand is the fact that the framework in question ("BSF4ooRexx", a bridge between ooRexx implemented in C++ and Java) is *not* part of any class hierarchy in the module(s) nor related to any specific module. A simple example ooRexx program using a Java class that gets intertwined with the three test modules mod_A (exports mtest1), mod_B (requires mod_A, exports mtest2 to mod_C), mod_C (exports mtest3): o=.bsf~new("mtest3.Class03A") -- create Java object, get and assign proxy ooRexx object say "o:" o "o~myClassName:" o~myClassName -- get (static) field value in "mtest1.Class01A", accessible via inheritance rules ::requires BSF.CLS -- direct interpreter to load the Java bridge The basic logic is as follows: * load the class "mtest3.Class03A", reflectively get a constructor and create a Java object, store it in a Java repository return the key to allow looking up the object * ooRexx creates an ooRexx proxy object which will forward all unknown messages to the bridge, which in turn determines what is sought and uses reflection to carry out the desired operation * the second statement shows the ooRexx object name (the key into the Java registry) and uses the bridge to have it look up the field named "myClassName" (there is no message by that name on the ooRexx side, so the bridge is used to lookup the proxied Java object; a message is indicated by the message operator '~', the tilde, where the receiver is placed left of it and the message name right of it) 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). This logic has been working since Java 1.1 (sic!) throughout all Java versions using Java's reflection infrastructure. Java 9 currently breaks this. Is there currently (in the current implementation) any other means to achieve the same, mandatory needed functionality in Java 9 that I could use? --- 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. ---rony