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