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