Logging JVM Crashes in Java Services

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.

Tags: java logging error-handling JVM

Posted on Fri, 08 May 2026 14:12:00 +0000 by Sentosa