MethodHandler out of a non-static method
Remi Forax
forax at univ-mlv.fr
Tue Jun 8 08:34:33 UTC 2021
----- Mail original -----
> De: "Giuseppe Barbieri" <elect86 at gmail.com>
> À: "Maurizio Cimadamore" <maurizio.cimadamore at oracle.com>
> Cc: "panama-dev at openjdk.java.net'" <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
[2] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
>
>
>
> Il giorno gio 3 giu 2021 alle ore 11:33 Maurizio Cimadamore <
> 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