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