<html><body><div style="font-family: arial, helvetica, sans-serif; font-size: 12pt; color: #000000"><div><br></div><div><br></div><hr id="zwchr" data-marker="__DIVIDER__"><div data-marker="__HEADERS__"><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><b>From: </b>"tison" <wander4096@gmail.com><br><b>To: </b>"panama-dev" <panama-dev@openjdk.org><br><b>Sent: </b>Wednesday, September 27, 2023 11:59:08 AM<br><b>Subject: </b>Re: How to wrap Method handle behind a class?<br></blockquote></div><div data-marker="__QUOTED_TEXT__"><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><div dir="ltr"><div class="gmail_default" style="font-family:arial,sans-serif">OT - perhaps I should start a new thread, but the first things come to me when I talk to the FFM APIs:</div><div class="gmail_default" style="font-family:arial,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,sans-serif">1. Manually defining MemoryLayout can be clumsy. C# has a structure layout attribute for generating struct/class marshalling[1]</div><div class="gmail_default" style="font-family:arial,sans-serif">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 =。=</div><div class="gmail_default" style="font-family:arial,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,sans-serif">These are only rough ideas and I'm glad to know where I can start to learn the related work and previous discussions.</div></div></blockquote><div><br></div><div>Did you know that you can use jextract [1], that generates all the MethodHandle / structure layout for you ?</div><div><br data-mce-bogus="1"></div><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><div dir="ltr"><div class="gmail_default" style="font-family:arial,sans-serif"><br></div><div><div dir="ltr" class="gmail_signature"><div dir="ltr"><div><div dir="ltr"><div><div dir="ltr"><div><div dir="ltr"><div><font face="arial, sans-serif">Best,</font></div><div><font face="arial, sans-serif">tison.</font></div></div></div></div></div></div></div></div></div></div></div></blockquote><div><br></div><div>regards,<br data-mce-bogus="1"></div><div>Rémi Forax<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><div>[1] https://github.com/openjdk/jextract<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><div dir="ltr"><br><div><div class="gmail_default" style="font-family:arial,sans-serif">[1] <a href="https://learn.microsoft.com/en-us/dotnet/standard/native-interop/type-marshalling" target="_blank">https://learn.microsoft.com/en-us/dotnet/standard/native-interop/type-marshalling</a><br data-mce-bogus="1"></div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">tison <<a href="mailto:wander4096@gmail.com" target="_blank">wander4096@gmail.com</a>> 于2023年9月27日周三 17:53写道:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_default" style="font-family:arial,sans-serif">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:</div><div class="gmail_default" style="font-family:arial,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,sans-serif">private static final MethodHandle xxxNativeMethod = ...;</div><div class="gmail_default" style="font-family:arial,sans-serif">public static /* native */ ReturnType xxx(T1 t1, T2 t2, ...) {</div><div class="gmail_default" style="font-family:arial,sans-serif"> // validate</div><div class="gmail_default" style="font-family:arial,sans-serif"> return xxxNativeMethod.invoke(t1, t2, ...); // with return type coercion and exception handling</div><div class="gmail_default" style="font-family:arial,sans-serif">}</div><div class="gmail_default" style="font-family:arial,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,sans-serif">I'll try to do it and share it openly when I make an MVP.</div><div class="gmail_default" style="font-family:arial,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,sans-serif">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</div><div class="gmail_default" style="font-family:arial,sans-serif"><br></div><div><div dir="ltr" class="gmail_signature"><div dir="ltr"><div><div dir="ltr"><div><div dir="ltr"><div><div dir="ltr"><div><font face="arial, sans-serif">Best,</font></div><div><font face="arial, sans-serif">tison.</font></div><div><font face="arial, sans-serif"><br></font></div><div><font face="arial, sans-serif">[<span class="gmail_default" style="font-family:arial,sans-serif">1] </span></font><a href="https://github.com/apache/incubator-opendal/tree/main/bindings/java" target="_blank">https://github.com/apache/incubator-opendal/tree/main/bindings/java</a><br data-mce-bogus="1"></div></div></div></div></div></div></div></div></div></div><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">Maurizio Cimadamore <<a href="mailto:maurizio.cimadamore@oracle.com" target="_blank">maurizio.cimadamore@oracle.com</a>> 于2023年9月27日周三 17:43写道:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div>
<p>Glavo's suggestion is correct. If you want the method handle call
to apply the maximum set of conversions, you should use
`invokeWithArguments`.</p>
<p>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).</p>
<p>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).<br>
</p>
<p>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.</p>
<p>Cheers<br>
Maurizio<br>
</p>
<div>On 27/09/2023 10:29, Glavo wrote:<br>
</div>
<blockquote>
<div dir="ltr">
<div dir="ltr">See MethodHandle::invokeWithArguments.</div>
<div dir="ltr"><br>
</div>
<div>Glavo</div>
</div>
<br>
<div class="gmail_quote">
<div dir="ltr" class="gmail_attr">On Wed, Sep 27, 2023 at
5:14 PM tison <<a href="mailto:wander4096@gmail.com" target="_blank">wander4096@gmail.com</a>>
wrote:<br>
</div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div dir="ltr">
<div class="gmail_default" style="font-family:arial,sans-serif">I'm using OpenJDK 21
and prototyping FFM APIs.</div>
<div class="gmail_default" style="font-family:arial,sans-serif"><br>
</div>
<div class="gmail_default" style="font-family:arial,sans-serif">Instead of passing
the MethodHandle returned by linker.downcallHandle here
and there, I'm trying to wrap it into a NativeMethod
class:</div>
<div class="gmail_default" style="font-family:arial,sans-serif"><br>
</div>
<div class="gmail_default" style="font-family:arial,sans-serif">public final class
NativeMethod {<br>
private final String name;<br>
private final FunctionDescriptor descriptor;<br>
private final MethodHandle handle;<br>
</div>
<div class="gmail_default" style="font-family:arial,sans-serif"> public Object
invoke(Object... args) throws Throwable {<br>
return this.handle.invoke(args);<br>
}<br>
}<br>
</div>
<div class="gmail_default" style="font-family:arial,sans-serif"><br>
</div>
<div class="gmail_default" style="font-family:arial,sans-serif">But it seems the
varargs pass through is not quit fluent:</div>
<div class="gmail_default" style="font-family:arial,sans-serif"><br>
</div>
<div class="gmail_default" style="font-family:arial,sans-serif">java.lang.invoke.WrongMethodTypeException:
cannot convert MethodHandle(int)int to (Object[])Object<br>
<br>
at
java.base/java.lang.invoke.MethodHandle.asTypeUncached(MethodHandle.java:903)<br>
at
java.base/java.lang.invoke.MethodHandle.asType(MethodHandle.java:870)<br>
at
java.base/java.lang.invoke.Invokers.checkGenericType(Invokers.java:541)<br>
at
io.montumi.datafusion.core.NativeMethod.invoke(NativeMethod.java:22)<br>
</div>
<div class="gmail_default" style="font-family:arial,sans-serif"><br>
</div>
<div class="gmail_default" style="font-family:arial,sans-serif">While if I public the
handle and call invoke from the handle directly, all the
behavior is expected.</div>
<div class="gmail_default" style="font-family:arial,sans-serif"><br>
</div>
<div>
<div dir="ltr" class="gmail_signature">
<div dir="ltr">
<div>
<div dir="ltr">
<div>
<div dir="ltr">
<div>
<div dir="ltr">
<div><font face="arial, sans-serif">Best,</font></div>
<div><font face="arial, sans-serif">tison.</font></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</blockquote>
</div>
</blockquote>
</div>
</blockquote></div></blockquote></div><br></blockquote></div></div></body></html>