Exposing checked exceptions that a MethodHandle can throw
John Rose
john.r.rose at oracle.com
Mon May 22 18:29:40 UTC 2023
Thanks for the good response Remi.
This is part of a larger FAQ, “why are MHs hard to use?”
Part of the answer is “they model bytecode behavior”.
(Perhaps they should have been called BytecodeBehaviorHandles.)
Lifting such raw VM-level behaviors up into Java source code is
necessary, but it will never be pleasant, at least not until Java has
enough capabilities in its syntax and type system to model such beasties
without extra layers of object wrapping.
That would include fully incorporating exception checking into the
generic type system, a hard problem. It would also involve making some
way to name a Java method (perhaps as `Foo::bar` or `myFoo::bar` or some
lambda) but get a MH out of the expression. Also some kinds of varargs
processing might be needed to “add suger” to varargs-related MH
transforms.
The amount of Java language engineering necessary for such things is so
large it will never be done, if MHs are the only use case. There are
far too many important improvements to make. (Thought experiment:
Should we drop some part of the pattern matching work in order to make
room for method handle exception checks? I thought not.)
Perhaps in the future there will come a time when exception checking is
tracked and/or `Foo::bar` syntax is made more generic, and that will
benefit MHs, but if it happens it will be for a list of weighty reasons,
apart from MHs.
For now, MH code has to be written in a low-level style in Java source
code. (But it works beautifully at the assembly code level, if you are
spinning bytecodes.) For example, Java source methods which exist to
process MHs should just declare `throws Throwable`. Then you catch the
non-existent throwables at the boundary.
You can make this a little easier on yourself, sometimes, if you write a
higher-order helper function that takes a Throwable-throwing lambda and
sanitizes it down to the exceptions you expect. Then there’s just one
clunky `catch`, and your low-level Throwable-throwing code goes inside
lambda bodies.
On 21 May 2023, at 6:47, Remi Forax wrote:
> ----- Original Message -----
>> From: "-" <liangchenblue at gmail.com>
>> To: "core-libs-dev" <core-libs-dev at openjdk.org>
>> Sent: Sunday, May 21, 2023 6:52:44 AM
>> Subject: Exposing checked exceptions that a MethodHandle can throw
>
>> Hello,
>> I am eliciting a discussion on the feasibility of tracking checked
>> exceptions thrown by a MethodHandle. It is already requested in
>> https://bugs.openjdk.org/browse/JDK-8268116 as it appears useful in
>> the development of Foreign Function Interface API.
>
> At the bytecode level, checked exceptions are stored in an attribute
> associated to a method.
> https://docs.oracle.com/javase/specs/jvms/se20/html/jvms-4.html#jvms-4.7.5
>
> If you have a direct MethodHandle, you can already get the checked
> exceptions using Lookup.revealDirect() + MethodHandleInfo.reflectAs().
>
>>
>> Currently, explicit MethodHandle usages are hampered by the catch
>> block as the invoke methods are declared to throw any Throwable.
>> Could
>> it be possible that we specify the types of possible exceptions at
>> MethodHandle invocation, so that:
>> 1. Javac accepts code that just call the handle without ugly
>> try-catch block
>> 2. If the exceptions anticipated at invocation site are incompatible
>> with (i.e. more specific than) those declared by the invoked handle,
>> it can throw an exception like the existing
>> `WrongMethodTypeException`
>> eagerly.
>
> The bug you reference seems to be about runtime information, but the
> paragraph above is about type-checking information.
> The question here is "is the Java type system good enough to track
> checked exception in a backward compatible way ?"
> Practically, I believe the answer is no, you can not compose function
> with different type parameters representing exception, there is no
> varargs of type parameters, there is no default type argument for a
> type parameter, etc.
>
> It's also significant departure of the way the method handle API is
> created, the idea behind is that each combiner has the semantics of an
> existing bytecode. But all invoke* bytecodes are oblivious to
> exception. Said differently, the method handle API represent how the
> JVM works, not how Java the language works.
>
>>
>> Is such a plan feasible? Tracking of exceptions should be easy from
>> Direct MH and the MethodHandles combinators already, while the
>> invocation semantics update might be more complex, maybe in the form
>> of compiler-inserted stubs before the actual invoke calls. I wish
>> such
>> improvements can make MethodHandle more friendly to direct usages in
>> code, so users don't need to wrap MH invocations in try-catch blocks
>> everywhere.
>
> see above.
>
>>
>> Chen Liang
>
> Rémi
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/core-libs-dev/attachments/20230522/8c38a393/attachment.htm>
More information about the core-libs-dev
mailing list