[jep-334] Asymmetric method types of MHD vs MH

Brian Goetz brian.goetz at oracle.com
Tue Nov 20 13:28:06 UTC 2018

Thanks for poking into these new APIs.  This is a good question.

Your mental model is a good first-order approximation, but it has some 
risk; in the event of conflict, XxDesc's classes loyalty will be to 
Constant_Xxx_info (the classfile format), rather than its live-type 

MethodHandle embeds the invocation mode (static, virtual, interface, 
special) in the MH itself, so that you can treat the receiver as just 
another parameter.  This is tremendously useful as the primary purpose 
of method handles is to be invoked; it collapse four invocation modes 
into one.

DirectMethodHandleDesc models the classfile structure of an invocation; 
the MethodRef_info/NameAndType/invocation bytecode -- as shown in your 

     jshell> var mhd = (MethodHandleDesc)mh.describeConstable().get()
     mhd ==> MethodHandleDesc[VIRTUAL/PrintStream::println()void]

I think what you're saying is: there is enough information here to correctly compose the type() -- for virtual/special/interface, curry the owner type on -- and that this would provide alignment with the live MethodHandle behavior.

But, it would separate from the classfile Constant_MethodHandle_info behavior; what goes in the NameAndType here (for instance methods) is the receiver-less version.  Hence the conflict.

I think what is really going on here is that there are two types -- the MH type, and the lookup type; the latter is a property of the DMHDesc, while the former is a property of the MHDesc?

On 11/20/2018 7:06 AM, Michael van Acken wrote:
> While tracking down unexpected behavior in my compiler, I noticed that
> MethodHandleDesc and MethodHandle differ in what they list in their
> method type.  I was expecting that the MHD matches the MH, in that
> the receiver of a virtual method is included in the parameter list.
> Instead,
> it is omitted.  (See below for a jshell example.)
> As a compiler writer, I find the MH's unified view on static and virtual
> method types very helpful.  The current implementation's MHD class
> does not mirror this view, which means I would have to special case the
> method types for some operations.
> My mental model of the descriptor classes is, that they are one-to-one
> symbolic representations of their handle counterparts.  I am very confused
> by the difference in structure, with the receiver dropping out of the
> method type.
> |  Welcome to JShell -- Version 12-internal
> |  For an introduction type: /help intro
> jshell> import java.lang.invoke.*
> jshell> import java.lang.constant.*
> jshell> var l = MethodHandles.lookup()
> l ==>
> jshell> var mt = MethodType.methodType(Void.TYPE)
> mt ==> ()void
> jshell> var mh = l.findVirtual(java.io.PrintStream.class, "println", mt)
> mh ==> MethodHandle(PrintStream)void
> jshell> mh.type()
> $6 ==> (PrintStream)void
> jshell> mh.type().parameterCount()
> $7 ==> 1
> jshell> var mhd = (MethodHandleDesc)mh.describeConstable().get()
> mhd ==> MethodHandleDesc[VIRTUAL/PrintStream::println()void]
> jshell> mhd.methodType()
> $9 ==> MethodTypeDesc[()void]
> jshell> mhd.methodType().parameterCount()
> $10 ==> 0
> Regards,
> Michael van Acken

More information about the amber-dev mailing list