question on exports to

Peter Levart peter.levart at gmail.com
Wed Jun 1 16:57:23 UTC 2016


Hi Jochen,


On 06/01/2016 05:46 PM, Jochen Theodorou wrote:
>
>
> On 01.06.2016 14:43, Peter Levart wrote:
> [...]
>> I also don't wish to cause further confusion, but I have a feeling that
>> Jochen might have the following situation:
>>
>> - MyOtherLib contains classes and code that is using these classes
>> (invoking their methods), but it wishes to call those methods via an
>> indirection through a GeneralInvoker that happens to live in another 
>> module
>> - MyOtherLib is also using classes (invoking methods) from other modules
>> that it already has direct access to, but it wishes to call those
>> methods via an indirection through a GeneralInvoker too
>
> in the end I am trying to figure out step-by-step what I have to do 
> for the Groovy runtime to make it fully module compatible. That job is 
> similar to what is to be done for Nashorn or JRuby.
>
> In Groovy we have 2 callsite caching mechanisms, one is based on 
> invokedynamic, the other is using reflection and runtime class 
> generation. At least the later one will have to change a lot... up to 
> the point that I am wondering if we should not ditch it... which again 
> is difficult, because legacy code will still use it. Replacing the old 
> code to do internally MethodHandles might be an option though.. but 
> then again, the old API does not provide me with a Lookup object... 
> which is where things fall apart again.

Ah, sorry to hear there are other obstacles...

>
> Anyway... the groovy runtime would be almost something like java.base, 
> but instead of being like a root element, this one will have to sit in 
> the middle, because we depend on java as well.
>
>> If that is true, then perhaps there is a simpler solution that doesn't
>> require modifying the exports of any module.
>>
>> Make your TheInvoker take another argument of type MethodHandles.Lookup:
>>
>> public class TheInvoker{
>>      public static Object invoke(MethodHandles.Lookup lookup, Object
>> receiver, String name, Object... args) throws Throwable {
>>          Method m = receiver.getClass().getDeclaredMethod(name,
>> toClass(args));
>>          MethodHandle mh = lookup.unreflect(m).bindTo(receiver);
>>          return mh.invokeWithArguments(args);
>>      }
>> ...
>> }
>>
>> Then pass the appropriate lookup to it from where you call
>> TheInvoker.invoke (from MyOtherLib):
>>
>> TheInvoker.invoke(MethodHandles.lookup(), receiver, "methodName",
>> arguments...);
>
> receiver.getClass().getDeclaredMethod would fail, if I cannot access 
> the class of the receiver. 

No, for obtaining reflection objects you don't need language access 
rights. You need security permissions if security manager is installed, 
but that's independent of language access checks. Language access checks 
are performed when you call Method::invoke or Field::get, etc... or when 
you do Lookup::unreflect, but the later is performed against the "caller 
class" that is captured inside the Lookup object.

> So if "MyOtherLib is also using classes (invoking methods) from other 
> modules that it already has direct access to, but it wishes to call 
> those methods via an indirection through a GeneralInvoker too", then 
> this will fail without further precautions.
>
> In theory Lookup#findvirtual could be used in my example, but in the 
> real code I will most probably have to get all methods of that name, 
> to then filter the most fitting one, considering the argument types, 
> as well as potentially transforming arguments. And Lookup does not 
> provide me anything like MethodHandle[] for a given name.

So you can use normal Class.getDeclaredMethods() and choose among them 
for yourself. When you have resolved THE Method, you call 
Lookup::unreflect with it and decorate the resulting MH with needed 
transformations.


>
> bye Jochen

Regards, Peter



More information about the jigsaw-dev mailing list