A lot of questions around the configuration of a reflective style library

Peter Levart peter.levart at gmail.com
Mon Jul 11 11:49:04 UTC 2016


Hi Jochen,


On 07/11/2016 12:24 PM, Jochen Theodorou wrote:
>
>
> On 11.07.2016 11:43, Peter Levart wrote:
> [...]
>> Here's a simplified idea. Suppose MyReflection uses java reflection to
>> invoke target methods directly and it is already arranged so that
>> MyReflection has access to hidden methods in both M1 and M2 (let's take
>> the generated M1|M2Accessor(s) out of the picture for now - the idea can
>> be extended to include them later). Suppose that simplified MyReflection
>> is used to invoke just static methods in the module of the original 
>> caller:
>>
>> public class MyReflection {
>>
>>      public interface AccessToken {}
>>
>>      public static Object invoke(AccessToken accessToken,
>>                                  Class<?> target, String methodName,
>>                                  Class<?>[] parameterTypes, Object 
>> ... args)
>>          throws IllegalAccessException,
>>                 NoSuchMethodException,
>>                 InvocationTargetException
>>      {
>>          if (accessToken.getClass().getModule() != target.getModule()) {
>>              throw new IllegalAccessException("Cross module call");
>>          }
>>
>>          return target.getDeclaredMethod(methodName, parameterTypes)
>>                      // this is a reflective call, but it could as well
>> be a call made by generated accessor
>>                       .invoke(null, args);
>>      }
>> }
>>
>>
>> The original invoker and the hidden target method in M1 could then look
>> like:
>>
>> public class CM1 {
>>
>>      public static int hiddenAdd(int a, int b) {
>>          return a + b;
>>      }
>>
>>      // keep the instance of AccessToken private and only pass it to
>> MyReflection
>>      private static final MyReflection.AccessToken ACCESS =
>>          new MyReflection.AccessToken() {};
>>
>>      public static void main(String[] args) throws Exception {
>>          int sum = (Integer)
>>              MyReflection.invoke(ACCESS,
>>                                  CM1.class, "hiddenAdd", new 
>> Class<?>[]{int.class, int.class},
>>                                  10, 20);
>>      }
>> }
>>
>> As long as instance(s) of AccessToken implemented by classes in M1 are
>> kept private and only passed to MyReflection, MyReflection can verify
>> that the one that has access to such instance is an authorized caller so
>> it grants it access to hidden methods in M1.
>
> For me you are confirming, that with MethodHandles, it will become the 
> responsibility to check module access rights and that calls from 
> hidden M1 to hidden M2 become possible.
>
> bye Jochen
>

I think you misunderstood me. With MethodHandle(s) and Lookup(s) it is 
the responsibility of the Lookup object to check the access rights while 
Lookup object also acts a an access token as it caries the identity of 
the "obtainer" - the one that called Methodhandles.lookup() to obtain 
the instance.

The alternative that I presented 2nd is something that doesn't involve 
MethodHandle(s) or Lookup(s). In this alternative, when a central party 
(MyReflection) dispatches calls of multiple caller(s), each from its own 
module, it has to have privileged access to the target methods in all 
the modules where target methods live. The original caller must then 
"authenticate" somehow to the central party in order for central party 
to authorize the call. I presented a simple solution with a 
SecurityToken marker interface.

So if you take the MethodHandle/Lookup route, the checking is already 
there and follows JVM rules for bytecode invocations. If you take the 
route of exposing hidden classes to MyReflection, then you will have to 
provide the authentication and authorization yourself.

Regards, Peter



More information about the jigsaw-dev mailing list