Capturing Crash Information
Adding a Global Uncaught Exception Hook
To record unexpected failures, install a handler for uncaught exceptions at the thread level. This catches errors that escape typical try-catch blocks.
Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> {
String logEntry = String.format("[FATAL] Thread %s terminated: %s%n",
thread.getName(), throwable.toString());
recordCrashData(logEntry, throwable);
});
Writing to a Dedicated Crash Log
The recordCrashData method handles the output. Below is a implementation that appends a stack trace to a specific file, ensuring the directory exists first.
private static void recordCrashData(String message, Throwable ex) {
Path logDir = Paths.get("logs", "crashes");
try {
Files.createDirectories(logDir);
Path crashFile = logDir.resolve("jvm_crash.log");
StringBuilder builder = new StringBuilder();
builder.append(message);
for (StackTraceElement element : ex.getStackTrace()) {
builder.append(" at ").append(element.toString()).append("\n");
}
Files.writeString(crashFile, builder.toString(),
StandardOpenOption.CREATE, StandardOpenOption.APPEND);
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
Flushing Data Guarantees
The code above uses StandardOpenOption.APPEND and writes directly without buffering strategies. For more resilience, you can wrap the file stream in a logged channel that forces a physical disk sync after each write.
Alternative: Shutdown Hook Strategy
Register a JVM shutdown hook as a secondary safety net. This runs when the proces exits normally or via SIGTERM, but it does not cover native-level crashes (like segmentation faults). For those, configure JVM flags.
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
// final logging of pending buffers
}));
JVM-Level Crash Data
For true native crashes, set JVM flags to generate error reports. Update the service start script:
-XX:ErrorFile=/var/log/myapp/hs_err_pid%p.log -XX:+HeapDumpOnOutOfMemoryError \
-XX:HeapDumpPath=/var/log/myapp/
The ErrorFile flag designates a path for the HotSpot error log, and the heap dump flags capture memory state on OOM errors. Combining application-level hooks with these flags provides thorough data for debugging failures.