Hi,

Recent discussion on the wrapping of exceptions (any Throwable) in LinkageError 
be it for invokedynamic and BootstrapMethodError (a spec issue) or for 
signature polymorphic linkage (an implementation detail AFAICT) resulted in a 
more detailed look at the exception handling in the j.l.invoke code.

To partially fix signature polymorphic linkage i have made some small 
modifications [1] but i found i need to dig deeper as there are many other 
cases where Throwable is wrapped, specifically with the calls to 
MethodHandleStatic.newInternalError:

  /*non-public*/ static InternalError newInternalError(Throwable cause) {
      return new InternalError(cause);
  }

There is also MethodHandleStatic.uncaughtException

  /** Propagate unchecked exceptions and errors, but wrap anything checked and 
throw that instead. */
  /*non-public*/ static Error uncaughtException(Throwable ex) {
      if (ex instanceof Error)  throw (Error) ex;
      if (ex instanceof RuntimeException)  throw (RuntimeException) ex;
      throw newInternalError("uncaught exception", ex);
  }

There may be cases where these are interchangeable, it’s subtle, and i would be 
away of replacing calls to newInternalError with uncaughtException.

I propose the following:

1) change newInternalError(String message, Throwable cause) to 
newInternalError(String message, Exception cause)
We want to be clear that the cause is an Exception, since this method will 
always return InternalError with a message.

2) replace newInternalError(Throwable cause) with  
errorOrNewInternalError(Throwable ex)

    /*non-public*/ static Error errorOrNewInternalError(Throwable ex) {
        if (ex instanceof Error) return (Error) ex;
        return newInternalError("uncaught exception", ex);
    }

In all cases existing Errors will never be wrapped.

3) It’s tempting to rename uncaughtException with uncheckedOrNewInternalError.

Paul.

[1]
diff -r 248159c6e61a 
src/java.base/share/classes/java/lang/invoke/LambdaForm.java
--- a/src/java.base/share/classes/java/lang/invoke/LambdaForm.java      Wed Aug 
24 11:23:58 2016 -0700
+++ b/src/java.base/share/classes/java/lang/invoke/LambdaForm.java      Wed Aug 
24 15:31:29 2016 -0700
@@ -41,7 +41,6 @@
 import static java.lang.invoke.LambdaForm.BasicType.*;
 import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeStatic;
 import static java.lang.invoke.MethodHandleStatics.*;
-import java.util.Objects;

 /**
  * The symbolic, non-executable form of a method handle's invocation semantics.
@@ -856,7 +855,7 @@
                 System.out.println("LambdaForm compilation failed: " + this);
                 bge.printStackTrace(System.out);
             }
-        } catch (Error | Exception e) {
+        } catch (Exception e) {
             throw newInternalError(this.toString(), e);
         }
     }
diff -r 248159c6e61a 
src/java.base/share/classes/java/lang/invoke/MethodHandle.java
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandle.java    Wed Aug 
24 11:23:58 2016 -0700
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandle.java    Wed Aug 
24 15:31:29 2016 -0700
@@ -957,7 +957,7 @@
         if (!fail)  return needType;
         // elicit an error:
         this.asType(needType);
-        throw newInternalError("should not return", null);
+        throw newInternalError("should not return");
     }

     private void spreadArrayChecks(Class<?> arrayType, int arrayLength) {
diff -r 248159c6e61a 
src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java     
Wed Aug 24 11:23:58 2016 -0700
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java     
Wed Aug 24 15:31:29 2016 -0700
@@ -380,8 +380,11 @@
                 }
             }
         } catch (Throwable ex) {
-            if (ex instanceof LinkageError)
-                throw (LinkageError) ex;
+            // Pass through all instances of Error, thus ensuring errors such 
as
+            // ThreadDeath, StackOverflowException, OutOfMemoryException etc.
+            // are not wrapped
+            if (ex instanceof Error)
+                throw (Error) ex;
             else
                 throw new LinkageError(ex.getMessage(), ex);

Reply via email to