/* * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * 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. */ @SuppressWarnings("sync-override") @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: * *
** * Each exception is encoded before the exception it causes. */ @VMEntryPoint static String encodeThrowable(Throwable throwable) throws Throwable { try { Formatter enc = new Formatter(); List'|' '|' '|' [ '|' '|' '|' '|' ]* *