MethodHandler out of a non-static method

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Mon Jun 14 11:59:33 UTC 2021


Hi Giuseppe,
since you use a "virtual" method handle, you should first "bind it" to 
the receiver instance you want (using MethodHandle::bindTo).

E.g.

CLinker.getInstance().upcallStub(displayHandle.bindTo(teapotInstance),FunctionDescriptor.ofVoid(), scope);

Maurizio

On 14/06/2021 12:46, Giuseppe Barbieri wrote:
> Ok, I'm giving a try and use `::findVirtual` instead
> MethodHandle displayHandle =MethodHandles.lookup().findVirtual(teapot.getClass(),"display",MethodType.methodType(void.class));
> MemoryAddress displayStub =CLinker.getInstance().upcallStub(displayHandle,FunctionDescriptor.ofVoid(), scope);
> this fires:
> Exception in thread "main" java.lang.IllegalArgumentException: Arity 
> mismatch: (Teapot)void != ()v
> at 
> jdk.incubator.foreign/jdk.internal.foreign.abi.SharedUtils.checkFunctionTypes(SharedUtils.java:237)
> at 
> jdk.incubator.foreign/jdk.internal.foreign.abi.x64.sysv.CallArranger.getBindings(CallArranger.java:89)
> at 
> jdk.incubator.foreign/jdk.internal.foreign.abi.x64.sysv.CallArranger.arrangeUpcall(CallArranger.java:138)
> at 
> jdk.incubator.foreign/jdk.internal.foreign.abi.x64.sysv.SysVx64Linker.upcallStub(SysVx64Linker.java:111)
> at Teapot.main(Teapot.java:61)
>
> I can see the signature coherent with what you said. `::findVirtual` 
> does return signature of (Teapot)void
>
> So the problems seems to be inside
> FunctionDescriptor.ofVoid()
> or?
>
> Just for context, this is the signature of the function expecting 
> `displayStub`
> glutDisplayFunc(Addressable var0)
> And I also have
> MethodHandle glutDisplayFunc$MH()
> but I have no idea if this might play a role in this
>
>
> Il giorno mar 8 giu 2021 alle ore 10:34 Remi Forax <forax at univ-mlv.fr 
> <mailto:forax at univ-mlv.fr>> ha scritto:
>
>     >
>     > Another question, I'm trying to setup a test project with
>     Gradle, but I'm
>     > having a lot of issues, mainly because Gradle supports only up
>     to jdk 16.
>
>     Don't use Gradle with a not yet released JDK.
>     Gradle is very smart in the way it incrementally compile things,
>     but it has the price of not working with unreleased JDK.
>     A plain old Maven pom file is usually enough.
>
>
> This is quite a pity, because other than I'm used to relying on 
> Gradle, it actually can automate a lot and make the lives of us devs 
> much nicer.
> I'm actually working in this sense on the existing jextract plugin, 
> enhancing it.
>
> Also, just to say, Gradle actually works with the latest panama 17 
> build on the website, I managed to get the opengl example running 
> under Java (with the modification above regarding callbacks)
>
> The only problem I got so far, it's that I can't get it to work with 
> Kotlin, I keep getting errors on the imports, such as
> import jdk.incubator.ResourceScope
> I wonder if anyone here had success with it
>
>
> Giuseppe
>
> Il giorno mar 8 giu 2021 alle ore 10:34 Remi Forax <forax at univ-mlv.fr 
> <mailto:forax at univ-mlv.fr>> ha scritto:
>
>     ----- Mail original -----
>     > De: "Giuseppe Barbieri" <elect86 at gmail.com
>     <mailto:elect86 at gmail.com>>
>     > À: "Maurizio Cimadamore" <maurizio.cimadamore at oracle.com
>     <mailto:maurizio.cimadamore at oracle.com>>
>     > Cc: "panama-dev at openjdk.java.net
>     <mailto:panama-dev at openjdk.java.net>'"
>     <panama-dev at openjdk.java.net <mailto:panama-dev at openjdk.java.net>>
>     > Envoyé: Mardi 8 Juin 2021 09:26:15
>     > Objet: Re: MethodHandler out of a non-static method
>
>     > Thanks Maurizio and Remi, that helped
>     >
>     > Playing around I also got it working by using `bind`
>     >
>     > var displayHandle = MethodHandles.lookup().bind(teapot, "display",
>     > MethodType.methodType(void.class));
>     > var displayStub = CLinker.getInstance().upcallStub(displayHandle,
>     > FunctionDescriptor.ofVoid(), scope);
>     >
>     >
>     > What's the difference? Because I'd expect for `findVirtual` to
>     be used only
>     > on methods in implementation classes of abstract classes
>
>     A method handle unlike its name suggest is a function pointer, not
>     a method pointer.
>     So when you take a method and ask for a function pointer to it,
>     you have a supplementary first parameter, the one corresponding to
>     this.
>
>     By example, for
>      class A {
>        void foo(int i) { ... }
>      }
>
>     findVirtual returns a method handle with the signature: void foo(A
>     this, int i)
>
>     if you want to call a method handle always on the same instance,
>     you can use bindTo() (or insertArguments),
>     to say that the first argument is always that same
>
>       var a = new A();
>       var mh = ...
>       var boundMH = mh.bindTo(a);
>
>     Here, boundMH is "void foo(A this, int i)" with this = a
>     so it's a function with only one parameter, i of type int.
>
>     Now what bind() does is findVirtual(getClass(), ...) + bindTo,
>     on your example
>       var mh = lookup.findVirtual(teapot.getClass(), "display",
>     MethodType.methodType(void.class));
>       mh = mh.bindTo(teapot);
>
>     This idea that when you want to see a method as a function, you
>     can pass the receiver (the value of 'this') as first argument is
>     something very common in programming language,
>     you have it with method handle but you also have it when using
>     method reference in Java or bound method in Python [1], the method
>     bind in JavaScript [2], etc.
>
>     Using method reference:
>       // method reference seen as a function
>       BiConsumer<PrintStream, Object> consumer = PrintStream::println;
>
>       // bound method reference
>       PrintStream out = System.out;
>       Consumer<Object> consumer = out::println;
>
>
>     >
>     > Another question, I'm trying to setup a test project with
>     Gradle, but I'm
>     > having a lot of issues, mainly because Gradle supports only up
>     to jdk 16.
>
>     Don't use Gradle with a not yet released JDK.
>     Gradle is very smart in the way it incrementally compile things,
>     but it has the price of not working with unreleased JDK.
>     A plain old Maven pom file is usually enough.
>
>     >
>     > Is possible to run your application with a separate jdk
>     (toolchain) but
>     > then you need to use the `application` plugin and cannot rely
>     anymore on
>     > the comfortable Idea UI.
>     > Unless you switch and run your code using the IDE instead of
>     Gradle, but
>     > then I get into some other exceptions. Moreover, some imports
>     remain still
>     > unresolved.
>     >
>     > So, I'd like to skip this trainwreck all at once and ask directly if
>     > anybody here has a working base scenario with the latest EA jdk
>     17 and
>     > Gradle
>     >
>     >
>     > Thanks in advance
>
>     regards,
>     Rémi
>
>     [1] https://www.quora.com/What-is-a-bound-method-in-Python
>     <https://urldefense.com/v3/__https://www.quora.com/What-is-a-bound-method-in-Python__;!!GqivPVa7Brio!MfBhZklo69_CAfezNNfocg3RlP9fe1uwGktBEtp85Mc0tsevd_G6jwlFI4IiStiHZAyTHco$>
>     [2]
>     https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
>     <https://urldefense.com/v3/__https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind__;!!GqivPVa7Brio!MfBhZklo69_CAfezNNfocg3RlP9fe1uwGktBEtp85Mc0tsevd_G6jwlFI4IiStiHZPPonPE$>
>
>     >
>     >
>     >
>     > Il giorno gio 3 giu 2021 alle ore 11:33 Maurizio Cimadamore <
>     > maurizio.cimadamore at oracle.com
>     <mailto:maurizio.cimadamore at oracle.com>> ha scritto:
>     >
>     >> Hi Giuseppe
>     >>
>     >> On 02/06/2021 23:52, Giuseppe Barbieri wrote:
>     >> > Hi,
>     >> >
>     >> > excited from the last development, I came back giving a try
>     to the latest
>     >> > jdk build (the partial 17 available on the site) and I'm
>     trying to
>     >> > update/fix the opengl sample
>     >> >
>     >> > First of all, it looks like `jextract` doesn't accept anymore
>     the option
>     >> to
>     >> > produce an output jar. I had to manually compress the
>     resulting folder to
>     >> > zip and rename, before importing in the target project.
>     >>
>     >> We decided to simplify jextract and focus on source code
>     generation,
>     >> which seems to be the mode that most people want to work with,
>     and it's
>     >> also the "more primitive": you can derive classes (and jars)
>     from it.
>     >>
>     >> If you are using it in a project, you might consider directly
>     checking
>     >> in the extracted sources in your project. If you are using an
>     IDE, it is
>     >> going to improve your experience a little bit (the classfiles
>     generated
>     >> by the old jextract were poorly understood by some of the IDEs out
>     >> there, which led to issues in indexing).
>     >>
>     >
>     >
>     >
>     >
>     >
>     >>
>     >> >
>     >> > It'd be cool if jextract could output directly the jar (and
>     the sources)
>     >> >
>     >> > Coming back to my issue, how can I retrieve the MethodHandler
>     out of a
>     >> > non-static method?
>     >>
>     >> You mean you want to create a MethodHandle for an instance method?
>     >>
>     >> Let's see (I'll use jshell to make sure my code doesn't have
>     any typos
>     >> :-) ):
>     >>
>     >> ```
>     >> jshell> class Foo {
>     >>     ...> void greet(String msg) { System.out.println(msg); }
>     >>     ...> }
>     >> |  created class Foo
>     >>
>     >> jshell> import java.lang.invoke.*;
>     >>
>     >> jshell> MethodHandle greetMH =
>     >> MethodHandles.lookup().findVirtual(Foo.class, "greet",
>     >> MethodType.methodType(void.class, String.class));
>     >> greetMH ==> MethodHandle(Foo,String)void
>     >>
>     >> jshell> greetMH.invoke(new Foo(), "Panama");
>     >> Panama
>     >> ```
>     >>
>     >> Is this what you were looking for?
>     >>
>     >> Cheers
>     >> Maurizio
>     >>
>     >> >
>     >> >
>     >> > Thanks in advance
>


More information about the panama-dev mailing list