src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/TranslatedException.java
Index Unified diffs Context diffs Sdiffs Frames Patch New Old Previous File Next File
*** old/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/TranslatedException.java	Fri May 31 08:53:48 2019
--- new/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/TranslatedException.java	Fri May 31 08:53:47 2019

*** 20,45 **** --- 20,45 ---- * 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, Throwable cause) { super(message, cause); } /** * No need to record an initial stack trace since it will be manually overwritten. */
*** 47,100 **** --- 47,148 ---- @Override public Throwable fillInStackTrace() { return this; } private static Throwable create(String className, String message) { + /** + * 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) { // 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); } cls.getDeclaredConstructor(String.class); ! return initCause((Throwable) cls.getConstructor(String.class).newInstance(message), cause); ! } catch (Throwable ignore) { } ! } catch (Throwable translationFailure) { if (className.equals(TranslatedException.class.getName())) { // Chop the class name when boxing another TranslatedException ! return new TranslatedException(message); ! return initCause(new TranslatedException(message, translationFailure), cause); + } + return initCause(new TranslatedException(null, translationFailure), cause); + } } if (message == null) { return new TranslatedException(className); + /** + * 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; } return new TranslatedException(className + ": " + message); + + private static String decodeMessage(String value) { + if (value.length() == 0) { + return null; + } + return value.substring(1); } 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 with its cause is: * * <pre> * <exception class name> '|' <exception message> '|' <stack size> '|' [<class> '|' <method> '|' <file> '|' <line> '|' ]* * </pre> * ! * Each cause is appended after the exception is it the cause of. ! * Each exception is encoded before the exception it causes. */ @VMEntryPoint static String encodeThrowable(Throwable throwable) throws Throwable { try { Formatter enc = new Formatter(); ! Throwable current = throwable; ! do { ! enc.format("%s|%s|", current.getClass().getName(), encodedString(current.getMessage())); ! 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()))); StackTraceElement[] stackTrace = current.getStackTrace(); if (stackTrace == null) { stackTrace = new StackTraceElement[0]; } enc.format("%d|", stackTrace.length);
*** 103,119 **** --- 151,168 ---- 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|"; } } }
*** 144,159 **** --- 193,208 ---- @VMEntryPoint static Throwable decodeThrowable(String encodedThrowable) { try { int i = 0; String[] parts = encodedThrowable.split("\\|"); ! Throwable parent = null; ! Throwable result = null; ! Throwable cause = null; ! Throwable throwable = null; while (i != parts.length) { String exceptionClassName = parts[i++]; ! String exceptionMessage = decodeMessage(parts[i++]); ! Throwable throwable = create(exceptionClassName, exceptionMessage); ! throwable = create(exceptionClassName, exceptionMessage, cause); int stackTraceDepth = Integer.parseInt(parts[i++]); StackTraceElement[] suffix = getStackTraceSuffix(); StackTraceElement[] stackTrace = new StackTraceElement[stackTraceDepth + suffix.length]; for (int j = 0; j < stackTraceDepth; j++) {
*** 166,183 **** --- 215,228 ---- } stackTrace[j] = new StackTraceElement(className, methodName, fileName, lineNumber); } System.arraycopy(suffix, 0, stackTrace, stackTraceDepth, suffix.length); throwable.setStackTrace(stackTrace); if (parent != null) { parent.initCause(throwable); } else { result = throwable; } ! parent = throwable; } return result; } catch (Throwable t) { return new TranslatedException("Error decoding exception: " + encodedThrowable, t); + cause = throwable; + } + return throwable; + } catch (Throwable translationFailure) { + assert printStackTrace(translationFailure); ! return new TranslatedException("Error decoding exception: " + encodedThrowable, translationFailure); } } }

src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/TranslatedException.java
Index Unified diffs Context diffs Sdiffs Frames Patch New Old Previous File Next File