<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>