< prev index next >

src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/TranslatedException.java

Print this page

        

@@ -20,26 +20,26 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
 package jdk.vm.ci.hotspot;
 
-import java.lang.reflect.InvocationTargetException;
-import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.Formatter;
-import java.util.List;
 import java.util.Objects;
 
 /**
  * Support for translating exceptions between different runtime heaps.
  */
 @SuppressWarnings("serial")
 final class TranslatedException extends Exception {
 
-    private TranslatedException(String message, Throwable translationFailure) {
-        super("[" + translationFailure + "]" + Objects.toString(message, ""));
+    private TranslatedException(String message) {
+        super(message);
+    }
+
+    private TranslatedException(String message, Throwable cause) {
+        super(message, cause);
     }
 
     /**
      * No need to record an initial stack trace since it will be manually overwritten.
      */

@@ -47,102 +47,54 @@
     @Override
     public Throwable fillInStackTrace() {
         return this;
     }
 
-    /**
-     * Prints a stack trace for {@code throwable} and returns {@code true}. Used to print stack
-     * traces only when assertions are enabled.
-     */
-    private static boolean printStackTrace(Throwable throwable) {
-        throwable.printStackTrace();
-        return true;
-    }
-
-    private static Throwable initCause(Throwable throwable, Throwable cause) {
-        if (cause != null) {
-            try {
-                throwable.initCause(cause);
-            } catch (IllegalStateException e) {
-                // Cause could not be set or overwritten.
-                assert printStackTrace(e);
-            }
-        }
-        return throwable;
-    }
-
-    private static Throwable create(String className, String message, Throwable cause) {
+    private static Throwable create(String className, String message) {
         // Try create with reflection first.
         try {
             Class<?> cls = Class.forName(className);
-            if (cause != null) {
-                // Handle known exception types whose cause must be set in the constructor
-                if (cls == InvocationTargetException.class) {
-                    return new InvocationTargetException(cause, message);
-                }
-                if (cls == ExceptionInInitializerError.class) {
-                    return new ExceptionInInitializerError(cause);
-                }
-            }
             if (message == null) {
-                return initCause((Throwable) cls.getConstructor().newInstance(), cause);
+                return (Throwable) cls.getConstructor().newInstance();
             }
             cls.getDeclaredConstructor(String.class);
-            return initCause((Throwable) cls.getConstructor(String.class).newInstance(message), cause);
-        } catch (Throwable translationFailure) {
-            if (className.equals(TranslatedException.class.getName())) {
-                // Chop the class name when boxing another TranslatedException
-                return initCause(new TranslatedException(message, translationFailure), cause);
-            }
-            return initCause(new TranslatedException(null, translationFailure), cause);
+            return (Throwable) cls.getConstructor(String.class).newInstance(message);
+        } catch (Throwable ignore) {
         }
-    }
 
-    /**
-     * Encodes an exception message to distinguish a null message from an empty message.
-     *
-     * @return {@code value} with a space prepended iff {@code value != null}
-     */
-    private static String encodeMessage(String value) {
-        return value != null ? ' ' + value : value;
-    }
+        if (className.equals(TranslatedException.class.getName())) {
+            // Chop the class name when boxing another TranslatedException
+            return new TranslatedException(message);
+        }
 
-    private static String decodeMessage(String value) {
-        if (value.length() == 0) {
-            return null;
+        if (message == null) {
+            return new TranslatedException(className);
         }
-        return value.substring(1);
+        return new TranslatedException(className + ": " + message);
     }
 
     private static String encodedString(String value) {
         return Objects.toString(value, "").replace('|', '_');
     }
 
     /**
      * Encodes {@code throwable} including its stack and causes as a string. The encoding format of
-     * a single exception is:
+     * a single exception with its cause is:
      *
      * <pre>
      * <exception class name> '|' <exception message> '|' <stack size> '|' [<class> '|' <method> '|' <file> '|' <line> '|' ]*
      * </pre>
      *
-     * Each exception is encoded before the exception it causes.
+     * Each cause is appended after the exception is it the cause of.
      */
     @VMEntryPoint
     static String encodeThrowable(Throwable throwable) throws Throwable {
         try {
             Formatter enc = new Formatter();
-            List<Throwable> throwables = new ArrayList<>();
-            for (Throwable current = throwable; current != null; current = current.getCause()) {
-                throwables.add(current);
-            }
-
-            // Encode from inner most cause outwards
-            Collections.reverse(throwables);
-
-            for (Throwable current : throwables) {
-                enc.format("%s|%s|", current.getClass().getName(), encodedString(encodeMessage(current.getMessage())));
+            Throwable current = throwable;
+            do {
+                enc.format("%s|%s|", current.getClass().getName(), encodedString(current.getMessage()));
                 StackTraceElement[] stackTrace = current.getStackTrace();
                 if (stackTrace == null) {
                     stackTrace = new StackTraceElement[0];
                 }
                 enc.format("%d|", stackTrace.length);

@@ -151,18 +103,17 @@
                     if (frame != null) {
                         enc.format("%s|%s|%s|%d|", frame.getClassName(), frame.getMethodName(),
                                         encodedString(frame.getFileName()), frame.getLineNumber());
                     }
                 }
-            }
+                current = current.getCause();
+            } while (current != null);
             return enc.toString();
         } catch (Throwable e) {
-            assert printStackTrace(e);
             try {
                 return e.getClass().getName() + "|" + encodedString(e.getMessage()) + "|0|";
             } catch (Throwable e2) {
-                assert printStackTrace(e2);
                 return "java.lang.Throwable|too many errors during encoding|0|";
             }
         }
     }
 

@@ -193,16 +144,16 @@
     @VMEntryPoint
     static Throwable decodeThrowable(String encodedThrowable) {
         try {
             int i = 0;
             String[] parts = encodedThrowable.split("\\|");
-            Throwable cause = null;
-            Throwable throwable = null;
+            Throwable parent = null;
+            Throwable result = null;
             while (i != parts.length) {
                 String exceptionClassName = parts[i++];
-                String exceptionMessage = decodeMessage(parts[i++]);
-                throwable = create(exceptionClassName, exceptionMessage, cause);
+                String exceptionMessage = parts[i++];
+                Throwable throwable = create(exceptionClassName, exceptionMessage);
                 int stackTraceDepth = Integer.parseInt(parts[i++]);
 
                 StackTraceElement[] suffix = getStackTraceSuffix();
                 StackTraceElement[] stackTrace = new StackTraceElement[stackTraceDepth + suffix.length];
                 for (int j = 0; j < stackTraceDepth; j++) {

@@ -215,14 +166,18 @@
                     }
                     stackTrace[j] = new StackTraceElement(className, methodName, fileName, lineNumber);
                 }
                 System.arraycopy(suffix, 0, stackTrace, stackTraceDepth, suffix.length);
                 throwable.setStackTrace(stackTrace);
-                cause = throwable;
+                if (parent != null) {
+                    parent.initCause(throwable);
+                } else {
+                    result = throwable;
+                }
+                parent = throwable;
             }
-            return throwable;
-        } catch (Throwable translationFailure) {
-            assert printStackTrace(translationFailure);
-            return new TranslatedException("Error decoding exception: " + encodedThrowable, translationFailure);
+            return result;
+        } catch (Throwable t) {
+            return new TranslatedException("Error decoding exception: " + encodedThrowable, t);
         }
     }
 }
< prev index next >