How to wrap Method handle behind a class?

tison wander4096 at gmail.com
Wed Sep 27 09:59:08 UTC 2023


OT - perhaps I should start a new thread, but the first things come to me
when I talk to the FFM APIs:

1. Manually defining MemoryLayout can be clumsy. C# has a structure layout
attribute for generating struct/class marshalling[1]
2. I wonder if the new FFI calls can be JIT-ed. One of the major
performance impact factor of JNI is that they treat the foreign method as
black box and nothing optimize can be done =。=

These are only rough ideas and I'm glad to know where I can start to learn
the related work and previous discussions.

Best,
tison.

[1]
https://learn.microsoft.com/en-us/dotnet/standard/native-interop/type-marshalling


tison <wander4096 at gmail.com> 于2023年9月27日周三 17:53写道:

> Thanks for your quick response and suggestions! I realize that using
> static final MethodHandle and call invoke/invokeExact inside the wrapper
> class should be better. While the downside is I may have to duplicate some
> code like:
>
> private static final MethodHandle xxxNativeMethod = ...;
> public static /* native */ ReturnType xxx(T1 t1, T2 t2, ...) {
>     // validate
>     return xxxNativeMethod.invoke(t1, t2, ...); // with return type
> coercion and exception handling
> }
>
> I'll try to do it and share it openly when I make an MVP.
>
> FWIW, in the past months, I built a Java binding for a Rust lib named
> OpenDAL[1] using JNI since it requires JDK 8 compatibility. But this time
> I'd like to try out Datafusion with the new FFM APIs for fun :D
>
> Best,
> tison.
>
> [1] https://github.com/apache/incubator-opendal/tree/main/bindings/java
>
>
> Maurizio Cimadamore <maurizio.cimadamore at oracle.com> 于2023年9月27日周三
> 17:43写道:
>
>> Glavo's suggestion is correct. If you want the method handle call to
>> apply the maximum set of conversions, you should use `invokeWithArguments`.
>>
>> The price to pay is that, the further you move away from `invokeExact`
>> the slower the method call will go (because of the conversion code than
>> needs to surround the code itself).
>>
>> Also notice that, with your approach, the method handle wrapping the
>> function is not static final (it is final, but not static). This means it
>> is not a true JVM constant. This means your method handle call will
>> probably not be inlined very well. Wrapping with a record instead of a
>> plain class might be better because records fields are trusted. So if you
>> wrap a method handle in a NativeMethod _record_ and then you stick the
>> record instance in a static final field somewhere, that _should_ work as
>> expected (waving hands furiously).
>>
>> Anyway, of course all the above doesn't mean you shouldn't do what you
>> are trying to do - if performance is not a concern for you then your
>> approach is totally reasonable.
>>
>> Cheers
>> Maurizio
>> On 27/09/2023 10:29, Glavo wrote:
>>
>> See MethodHandle::invokeWithArguments.
>>
>> Glavo
>>
>> On Wed, Sep 27, 2023 at 5:14 PM tison <wander4096 at gmail.com> wrote:
>>
>>> I'm using OpenJDK 21 and prototyping FFM APIs.
>>>
>>> Instead of passing the MethodHandle returned by linker.downcallHandle
>>> here and there, I'm trying to wrap it into a NativeMethod class:
>>>
>>> public final class NativeMethod {
>>>     private final String name;
>>>     private final FunctionDescriptor descriptor;
>>>     private final MethodHandle handle;
>>>     public Object invoke(Object... args) throws Throwable {
>>>         return this.handle.invoke(args);
>>>     }
>>> }
>>>
>>> But it seems the varargs pass through is not quit fluent:
>>>
>>> java.lang.invoke.WrongMethodTypeException: cannot convert
>>> MethodHandle(int)int to (Object[])Object
>>>
>>> at
>>> java.base/java.lang.invoke.MethodHandle.asTypeUncached(MethodHandle.java:903)
>>> at java.base/java.lang.invoke.MethodHandle.asType(MethodHandle.java:870)
>>> at
>>> java.base/java.lang.invoke.Invokers.checkGenericType(Invokers.java:541)
>>> at io.montumi.datafusion.core.NativeMethod.invoke(NativeMethod.java:22)
>>>
>>> While if I public the handle and call invoke from the handle directly,
>>> all the behavior is expected.
>>>
>>> Best,
>>> tison.
>>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/panama-dev/attachments/20230927/7f0c10f3/attachment.htm>


More information about the panama-dev mailing list