Hi,

On 06/01/2016 12:03 PM, Alan Bateman wrote:
On 01/06/2016 09:34, Jochen Theodorou wrote:
:

This now looks to me like this... GeneralInvoker will have to call generalInvokerModule.addReads(myOtherLibModule), to enable to inspect the classes from that library. It will then spawn a layer with a named module, which contains the invocation code. This layerModule will contain code to call layerModule.addReads(myOtherLibModule), so it can access the classes in MyOtherLib if they are exported.... and since that is not yet the case, I will have to cause MyOtherLib to call myOtherLib.addExports("my.lib", layerModule).

Which still means I cannot replace reflection completely, since it does not have to cause MyOtherLib to call myOtherLib.addExports("my.lib", layerModule). Or it means I still lack understanding - which would not surprise me at all.
I don't wish to cause confusion in this thread but I think what you are looking for is:

1. MyOtherLib declares`requires GeneralInvoker`.

2. GeneralInvoker resolves "MyOtherLib" to create a configuration, that configuration is then instantiated as a module layer. There will be at least one module in that layer, maybe others if there are other dependences. GeneralInvoker will use findModule to locate the module named "MyOtherLib".

3. GeneralInvoker will use Module.addExports to export com.foo.gi to the runtime module MyOtherLib (from the thread then I gather than com.foo.gi is not exported, at least not unconditionally). This will allow the code in my.lib.SomeClassOfTheLibrary to invoke the public invoke method in com.foo.gi.TheInvoker.

4. The static initializer in my.lib.SomeClassOfTheLibrary will export my.lib to GeneralInvoker using Module.addExports. Again, I'm assuming that my.lib is not exported unconditionally. This one might be strange and non obvious but arises because qualified export aren't supported across layers. The "no forward reference" rule should be clear, it would be a security hazard. The "no back reference" (mean qualified exports to modules in parent layers) is a discussion point. It's useful in some scenario (like this one), not useful with static references because it would not make sense. This is a topic in itself and I don't wish to complicate your cage fight by going into this here.

With #4 then it allows GeneralInvoker to invoke the public methods in MyOtherLib's my.lib package.

As Alex noted, we need to write-up some of these "dynamic module" scenarios so there are pictures and examples to point at.

-Alan.

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

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...);


Would that work?

Regards, Peter

Reply via email to