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