Exceptions thrown when linking sig-poly methods and indy

David Holmes david.holmes at oracle.com
Tue Aug 23 00:19:23 UTC 2016


On 23/08/2016 9:12 AM, Uwe Schindler wrote:
> Hi,
>
> from my understanding of the spec:
>
>> As per my comments in the bug report I think the specification parts
>> that state to wrap all "exceptions" are too strict (for want of a better
>> word). One view is that they should only consider synchronous exceptions
>> directly triggered by a problem with resolution. Another possibility is
>> that "exception" was not intended to mean "any exception instance being
>> a subclass of Throwable", but rather was intended to be Exception - and
>> hence all subclasses of Error would be excluded.
>
> I think the spec says "exception" not "throwable", so only "Exception" subclasses should be wrapped. Errors should just be rethrown or not catched at all.

"exception" (lower-case 'e') is a general term, all of the objects that 
can be caught in a catch block are exceptions. If you want to refer to 
specific types of exceptions then it needs to be clear e.g. Throwable, 
Exception, Error, etc - actual type names with capitals.

>> Or the spec is mostly right and (other than truly async exceptions like
>> ThreadDeath) any exception encountered due to the linking should be
>> wrapped.
>
> Why only have special cases for such types? To me "Error" in general should never-ever be wrapped!

Async exceptions can be considered special cases as they are not caused 
by the code being executed.

Cheers,
David

> Uwe
>
>> There are other places in the VM and libraries where exception wrapping
>> occurs but I'm not sure if we have special handling for specific kinds
>> of exceptions (Exceptions thrown during static initialization;
>> Exceptions thrown during class loading/linking/resolution; exceptions
>> thrown when a task is submitted to an Executor; etc).
>>
>> Cheers,
>> David
>>
>> On 23/08/2016 8:22 AM, Paul Sandoz wrote:
>>> Hi,
>>>
>>> For methods that make an appeal to Java code such as an up call from
>> HotSpot to Java for linking signature-polymorphic methods or linking indy call
>> sites (invoking bootstrap methods) it’s possible that certain important
>> exceptions get wrapped in a LinkageError or a BootstrapMethodError. Such
>> important exceptions are ThreadDeath, StackOverflow and possibly OOME.
>>>
>>> Some j.u.concurrent classes were updated to use VarHandles and this now
>> very occasionally results in a test failure where ThreadDeath is wrapped in
>> LinkageError and thus thread-based JDK code reacts differently.
>>>
>>> See https://bugs.openjdk.java.net/browse/JDK-8163553.
>>>
>>> It’s easier to reproduce by updating the failing test with an indy [1], which
>> fails with various errors such as:
>>>
>>> Exception in thread "Thread-0" java.lang.BootstrapMethodError: call site
>> initialization exception
>>> 	at java.lang.invoke.CallSite.makeSite(java.base/CallSite.java:347)
>>> 	at
>> java.lang.invoke.MethodHandleNatives.linkCallSiteImpl(java.base/MethodHa
>> ndleNatives.java:250)
>>> 	at
>> java.lang.invoke.MethodHandleNatives.linkCallSite(java.base/MethodHandle
>> Natives.java:240)
>>> 	at Stop.lambda$test$1(Stop.java:15)
>>> 	at java.lang.Thread.run(java.base/Thread.java:843)
>>> Caused by: java.lang.ThreadDeath
>>> 	at java.lang.Thread.stop(java.base/Thread.java:948)
>>> 	at
>> java.lang.ThreadGroup.stopOrSuspend(java.base/ThreadGroup.java:698)
>>> 	at java.lang.ThreadGroup.stop(java.base/ThreadGroup.java:610)
>>> 	at Stop.lambda$test$2(Stop.java:32)
>>> 	... 1 more
>>>
>>> or more obscurely (and erroneously):
>>>
>>> Exception in thread "Thread-0" java.lang.InternalError:
>> DMH.invokeStatic__V=Lambda(a0:L)=>{
>>>     t1:L=DirectMethodHandle.internalMemberName(a0:L);
>>>     t2:V=MethodHandle.linkToStatic(t1:L);void}
>>> 	at
>> java.lang.invoke.MethodHandleStatics.newInternalError(java.base/MethodH
>> andleStatics.java:108)
>>> 	at
>> java.lang.invoke.LambdaForm.compileToBytecode(java.base/LambdaForm.ja
>> va:816)
>>> 	at
>> java.lang.invoke.DirectMethodHandle.makePreparedLambdaForm(java.base
>> /DirectMethodHandle.java:249)
>>> 	at
>> java.lang.invoke.DirectMethodHandle.preparedLambdaForm(java.base/Dire
>> ctMethodHandle.java:186)
>>> 	at
>> java.lang.invoke.DirectMethodHandle.preparedLambdaForm(java.base/Dire
>> ctMethodHandle.java:175)
>>> 	at
>> java.lang.invoke.DirectMethodHandle.make(java.base/DirectMethodHandle.
>> java:88)
>>> 	at
>> java.lang.invoke.MethodHandles$Lookup.getDirectMethodCommon(java.bas
>> e/MethodHandles.java:2035)
>>> 	at
>> java.lang.invoke.MethodHandles$Lookup.getDirectMethodNoSecurityManag
>> er(java.base/MethodHandles.java:1992)
>>> 	at
>> java.lang.invoke.MethodHandles$Lookup.getDirectMethodForConstant(java.
>> base/MethodHandles.java:2223)
>>> 	at
>> java.lang.invoke.MethodHandles$Lookup.linkMethodHandleConstant(java.b
>> ase/MethodHandles.java:2172)
>>> 	at
>> java.lang.invoke.MethodHandleNatives.linkMethodHandleConstant(java.bas
>> e/MethodHandleNatives.java:499)
>>> 	at Stop.lambda$test$1(Stop.java:15)
>>> 	at java.lang.Thread.run(java.base/Thread.java:843)
>>> Caused by: java.lang.ThreadDeath
>>> 	at java.lang.Thread.stop(java.base/Thread.java:948)
>>> 	at
>> java.lang.ThreadGroup.stopOrSuspend(java.base/ThreadGroup.java:698)
>>> 	at java.lang.ThreadGroup.stop(java.base/ThreadGroup.java:610)
>>> 	at Stop.lambda$test$2(Stop.java:32)
>>> 	... 1 more
>>>
>>>
>>> The invokedynamic specification states that a linking exception be wrapped
>> in BootstrapMethodError (a subtype of LinkageError):
>>>
>>>   https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-
>> 6.5.invokedynamic
>>>
>>>
>>> I think we need to review how we manage certain special Error types
>> thrown from linking, be the thrown directly or extracted from a known
>> wrapping exception and re-thrown.
>>>
>>> Certainly there are cases when linking an indy call set where
>> BootstrapMethodError should be thrown but is not (see above), but in
>> general how should we treat the occurrence of a ThreadDeath,
>> StackOverflow or OOME (or VirtualMachineError)?
>>>
>>> Should such exceptions be wrapped or thrown directly? if the latter that
>> would require a specification update for invokedynamic.
>>>
>>> If they are wrapped should the VM check the cause, unwrap for special
>> cases, and rethrow the cause?
>>>
>>> Paul.
>>>
>>> [1]
>>> import java.util.concurrent.CountDownLatch;
>>>
>>> public class Stop {
>>>
>>>     public static void main(String[] args) throws Exception {
>>>         test();
>>>     }
>>>
>>>     public static void test() throws Exception {
>>>         final CountDownLatch ready = new CountDownLatch(1);
>>>         final ThreadGroup group = new ThreadGroup("");
>>>
>>>         final Thread second = new Thread(group, () -> {
>>>             ready.countDown();
>>>             final Runnable r = () -> { System.out.println("RUN"); };
>>>             r.run();
>>>             while (true) {
>>>                 try {
>>>                     Thread.sleep(60000);
>>>                 } catch (InterruptedException shouldNotHappen) {
>>>                 }
>>>             }
>>>         });
>>>
>>>         final Thread first = new Thread(group, () -> {
>>>             // Wait until "second" is started
>>>             try {
>>>                 ready.await();
>>>             } catch (InterruptedException shouldNotHappen) {
>>>             }
>>>             // Now stop the group
>>>             group.stop();
>>>         });
>>>
>>>         // Launch two threads as part of the same thread group
>>>         first.start();
>>>         second.start();
>>>
>>>         // Check that the second thread is terminated when the
>>>         // first thread terminates the thread group.
>>>         second.join();
>>>         // Test passed - if never get here the test times out and fails.
>>>     }
>>> }
>>>
>


More information about the jdk9-dev mailing list