diff --git a/base/src/main/java/de/staropensource/engine/base/Engine.java b/base/src/main/java/de/staropensource/engine/base/Engine.java index 0a97aa0a8..057e18d88 100644 --- a/base/src/main/java/de/staropensource/engine/base/Engine.java +++ b/base/src/main/java/de/staropensource/engine/base/Engine.java @@ -290,8 +290,8 @@ public final class Engine extends SubsystemClass { new Engine(); } catch (RuntimeException exception) { Logger.error("Engine initialization failed"); - Logger.error(Miscellaneous.getThrowableHeader(exception.getCause())); - for (String line : Miscellaneous.stackTraceAsString(exception.getCause(), true).split("\n")) + Logger.error(Miscellaneous.throwableHeader(exception.getCause())); + for (String line : Miscellaneous.stacktraceAsString(exception.getCause(), true).split("\n")) Logger.error(line); throw new RuntimeException("Engine initialization failed", exception.getCause()); diff --git a/base/src/main/java/de/staropensource/engine/base/logging/backend/CrashHandler.java b/base/src/main/java/de/staropensource/engine/base/logging/backend/CrashHandler.java index 017dbc64b..bdb16481e 100644 --- a/base/src/main/java/de/staropensource/engine/base/logging/backend/CrashHandler.java +++ b/base/src/main/java/de/staropensource/engine/base/logging/backend/CrashHandler.java @@ -107,13 +107,13 @@ public final class CrashHandler { output .append("\nCaused by:") .append("\nNo throwable has been passed."); - else + else { + output .append("\n") - .append(Miscellaneous.getThrowableHeader(throwable)) - .append("\n") - .append(Miscellaneous.stackTraceAsString(throwable, true)) + .append(Miscellaneous.stacktraceAsStringRecursive(throwable, true, true)) .append("\n"); + } output.append("\nMessage: \n") .append(message) @@ -293,7 +293,7 @@ public final class CrashHandler { .append(thread.isDaemon()) .append("):") .append("\n") - .append(Miscellaneous.stackTraceAsString(stacktraces.get(thread), false)) + .append(Miscellaneous.stacktraceAsString(stacktraces.get(thread), false)) .append("\n"); } output.append("\n"); diff --git a/base/src/main/java/de/staropensource/engine/base/utility/FileAccess.java b/base/src/main/java/de/staropensource/engine/base/utility/FileAccess.java index 927a37814..53a4c7cde 100644 --- a/base/src/main/java/de/staropensource/engine/base/utility/FileAccess.java +++ b/base/src/main/java/de/staropensource/engine/base/utility/FileAccess.java @@ -190,7 +190,7 @@ public final class FileAccess { if (Files.exists(path)) Logger.error("Deleting file or directory \"" + path + "\" failed"); } catch (Exception exception) { - Logger.error("File or directory \"" + path + "\" could not be deleted\n" + Miscellaneous.getThrowableHeader(exception) + "\n" + Miscellaneous.stackTraceAsString(exception, true)); + Logger.error("File or directory \"" + path + "\" could not be deleted\n" + Miscellaneous.throwableHeader(exception) + "\n" + Miscellaneous.stacktraceAsString(exception, true)); } } } diff --git a/base/src/main/java/de/staropensource/engine/base/utility/misc/Miscellaneous.java b/base/src/main/java/de/staropensource/engine/base/utility/misc/Miscellaneous.java index 21494e87d..af5b5f3a4 100644 --- a/base/src/main/java/de/staropensource/engine/base/utility/misc/Miscellaneous.java +++ b/base/src/main/java/de/staropensource/engine/base/utility/misc/Miscellaneous.java @@ -23,6 +23,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.lang.ref.WeakReference; +import java.lang.reflect.InvocationTargetException; import java.util.*; import java.util.stream.Collectors; @@ -120,7 +121,7 @@ public final class Miscellaneous { * @return {@link Throwable} header * @since v1-alpha9 */ - public static @NotNull String getThrowableHeader(@NotNull Throwable throwable) { + public static @NotNull String throwableHeader(@NotNull Throwable throwable) { return "Caused by: " + throwable.getClass().getName() + (throwable.getMessage() == null ? "" : ": " + throwable.getMessage()); } @@ -128,13 +129,13 @@ public final class Miscellaneous { * Converts an array of {@link StackTraceElement}s into a regular string. * * @param stacktrace array of {@link StackTraceElement}s to convert - * @param indent if all lines should be indented with a single tab. + * @param indent if all lines shall be indented with a single tab. * Enabling this will cause the output of this method * to mimic the JVM's throwable handling output. * @return specified stack trace as a String * @since v1-alpha9 */ - public static @NotNull String stackTraceAsString(@NotNull StackTraceElement @NotNull [] stacktrace, boolean indent) { + public static @NotNull String stacktraceAsString(@NotNull StackTraceElement @NotNull [] stacktrace, boolean indent) { StringBuilder output = new StringBuilder(); for (StackTraceElement element : stacktrace) { @@ -153,13 +154,58 @@ public final class Miscellaneous { * Converts an array of {@link StackTraceElement}s into a regular string. * * @param throwable throwable to derive the stacktrace from - * @param indent if all lines should be indented with a single tab. + * @param indent if all lines shall be indented with a single tab. * Enabling this will cause the output of this method * to mimic the JVM's throwable handling output. * @return specified stack trace as a String * @since v1-alpha9 */ - public static @NotNull String stackTraceAsString(@NotNull Throwable throwable, boolean indent) { - return stackTraceAsString(throwable.getStackTrace(), indent); + public static @NotNull String stacktraceAsString(@NotNull Throwable throwable, boolean indent) { + return stacktraceAsString(throwable.getStackTrace(), indent); + } + + /** + * Returns the full stack trace of a {@link Throwable}. + *
+ * This method recursively resolves, converts and then + * returns every {@link Throwable} and stacktrace found. + * + * @param throwable throwable to recursively convert + * @param indent if all lines shall be indented with a single tab. + * Enabling this will cause the output of this method + * to mimic the JVM's throwable handling output. + * @param includeHeader if to include the throwable header (see {@link #throwableHeader(Throwable)}) + * @return full stack trace + * @since v1-alpha9 + */ + public static @NotNull String stacktraceAsStringRecursive(@NotNull Throwable throwable, boolean indent, boolean includeHeader) { + StringBuilder output = new StringBuilder(); + + // Append header and stacktrace + if (includeHeader) + output + .append(throwableHeader(throwable)) + .append("\n"); + output.append(stacktraceAsString(throwable, indent)); + + // Process recursively + if (throwable.getCause() != null) + output + .append("\n") + .append(stacktraceAsStringRecursive(throwable.getCause(), indent, includeHeader)); + if (throwable instanceof ClassNotFoundException exception) + output + .append("\n") + .append(stacktraceAsStringRecursive(exception.getException(), indent, includeHeader)); + if (throwable instanceof ExceptionInInitializerError exception) + output + .append("\n") + .append(stacktraceAsStringRecursive(exception.getException(), indent, includeHeader)); + if (throwable instanceof InvocationTargetException exception) + output + .append("\n") + .append(stacktraceAsStringRecursive(exception.getTargetException(), indent, includeHeader)); + + return output.toString(); } } diff --git a/testapp/src/main/java/de/staropensource/engine/testapp/Main.java b/testapp/src/main/java/de/staropensource/engine/testapp/Main.java index 4d5c16d25..8ae3103f0 100644 --- a/testapp/src/main/java/de/staropensource/engine/testapp/Main.java +++ b/testapp/src/main/java/de/staropensource/engine/testapp/Main.java @@ -148,22 +148,6 @@ public final class Main { Engine.getInstance().shutdown(); }); - - // Print render loop failures - StringBuilder message = new StringBuilder(); - message.append("Render loop failed on some windows:\n"); - - for (Window windowFailed : renderLoopFailures.keySet()) - message - .append("-> ") - .append(window) - .append(": ") - .append(Miscellaneous.getThrowableHeader(renderLoopFailures.get(windowFailed))) - .append("\n") - .append(Miscellaneous.stackTraceAsString(renderLoopFailures.get(windowFailed), true)) - .append("\n"); - - Logger.crash(message.toString()); } catch (Exception exception) { Logger.crash("Caught throwable in main thread:", exception); }