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 open Cdiff src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/TranslatedException.java

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

Print this page

        

*** 20,45 **** * or visit www.oracle.com if you need additional information or have any * questions. */ package jdk.vm.ci.hotspot; import java.util.Arrays; import java.util.Formatter; import java.util.Objects; /** * Support for translating exceptions between different runtime heaps. */ @SuppressWarnings("serial") final class TranslatedException extends Exception { ! 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. */ --- 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, "")); } /** * No need to record an initial stack trace since it will be manually overwritten. */
*** 47,100 **** @Override public Throwable fillInStackTrace() { return this; } ! private static Throwable create(String className, String message) { // Try create with reflection first. try { Class<?> cls = Class.forName(className); if (message == null) { ! return (Throwable) cls.getConstructor().newInstance(); } cls.getDeclaredConstructor(String.class); ! return (Throwable) cls.getConstructor(String.class).newInstance(message); ! } catch (Throwable ignore) { ! } ! if (className.equals(TranslatedException.class.getName())) { // Chop the class name when boxing another TranslatedException ! return new TranslatedException(message); } ! if (message == null) { ! return new TranslatedException(className); } ! 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 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. */ @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())); StackTraceElement[] stackTrace = current.getStackTrace(); if (stackTrace == null) { stackTrace = new StackTraceElement[0]; } enc.format("%d|", stackTrace.length); --- 47,148 ---- @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) { // 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 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); ! } } ! /** ! * 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; } ! ! 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 is: * * <pre> * <exception class name> '|' <exception message> '|' <stack size> '|' [<class> '|' <method> '|' <file> '|' <line> '|' ]* * </pre> * ! * Each exception is encoded before the exception it causes. */ @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()))); StackTraceElement[] stackTrace = current.getStackTrace(); if (stackTrace == null) { stackTrace = new StackTraceElement[0]; } enc.format("%d|", stackTrace.length);
*** 103,119 **** 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) { try { return e.getClass().getName() + "|" + encodedString(e.getMessage()) + "|0|"; } catch (Throwable e2) { return "java.lang.Throwable|too many errors during encoding|0|"; } } } --- 151,168 ---- if (frame != null) { enc.format("%s|%s|%s|%d|", frame.getClassName(), frame.getMethodName(), encodedString(frame.getFileName()), frame.getLineNumber()); } } ! } 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 **** @VMEntryPoint static Throwable decodeThrowable(String encodedThrowable) { try { int i = 0; String[] parts = encodedThrowable.split("\\|"); ! Throwable parent = null; ! Throwable result = null; while (i != parts.length) { String exceptionClassName = parts[i++]; ! 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++) { --- 193,208 ---- @VMEntryPoint static Throwable decodeThrowable(String encodedThrowable) { try { int i = 0; String[] parts = encodedThrowable.split("\\|"); ! Throwable cause = null; ! Throwable throwable = null; while (i != parts.length) { String exceptionClassName = parts[i++]; ! String exceptionMessage = decodeMessage(parts[i++]); ! 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 **** } 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); } } } --- 215,228 ---- } stackTrace[j] = new StackTraceElement(className, methodName, fileName, lineNumber); } System.arraycopy(suffix, 0, stackTrace, stackTraceDepth, suffix.length); throwable.setStackTrace(stackTrace); ! 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