JVM application shutdown hooks (original) (raw)

Laurent Bourgès bourges.laurent at gmail.com
Thu Jun 27 09:57:14 UTC 2013


Dear members,

I have a problem within an external library using one JVM Shutdown hook to perform resource cleanup (socket, lock file deletion ...) that seems buggy in java web start environment: sometimes the JVM reports an IllegalStateException happenning during that shutdown hook.

This library uses java.util.logging to log warnings and exceptions but none is logged (console or java trace files).

The 'lost' log messages is related to the LogManager's shutdown hook: // This private class is used as a shutdown hook. // It does a "reset" to close all open handlers. private class Cleaner extends Thread {

    private Cleaner() {
        /* Set context class loader to null in order to avoid
         * keeping a strong reference to an application classloader.
         */
        this.setContextClassLoader(null);
    }

    public void run() {
        // This is to ensure the LogManager.<clinit> is completed
        // before synchronized block. Otherwise deadlocks are possible.
        LogManager mgr = manager;

        // If the global handlers haven't been initialized yet, we
        // don't want to initialize them just so we can close them!
        synchronized (LogManager.this) {
            // Note that death is imminent.
            deathImminent = true;
            initializedGlobalHandlers = true;
        }

        // Do a reset to close all active handlers.
        reset();
    }
}

Without any log handler, the log messages are lost during shutdown ! I think it is annoying as it avoids me getting log and exceptions ...

FYI, the ApplicationShutdownHooks class executes all 'application' hooks concurrently: static void runHooks() { Collection threads; synchronized(ApplicationShutdownHooks.class) { threads = hooks.keySet(); hooks = null; }

    for (Thread hook : threads) {
        hook.start();
    }
    for (Thread hook : threads) {
        try {
            hook.join();
        } catch (InterruptedException x) { }
    }
}

So it is not possible to define hook priorities ...

However, I looked at the JVM Shutdown class which supports hook priorities and I think that the J.U.L Cleaner hook should run after all application hooks. Here are the current Shutdown priorities: // The system shutdown hooks are registered with a predefined slot. // The list of shutdown hooks is as follows: // (0) Console restore hook // (1) Application hooks // (2) DeleteOnExit hook

Moreover, as a RFE, it could be useful for applications to be able to define hook priorities within an application: I did that several times registering only 1 shutdown hook and handling correct ordering on my own ... but could be supported by the JDK itself.

Finally, here are (below) the Open JDK8 usages of Runtime.addShutdownHook [19 occurrences] which are more system hooks than application hooks: com.sun.imageio.stream StreamCloser.java StreamCloser addToQueue run 101: Runtime.getRuntime().addShutdownHook(streamCloser); java.util.logging LogManager.java LogManager LogManager 255: Runtime.getRuntime().addShutdownHook(new Cleaner()); sun.font SunFontManager.java SunFontManager createFont2D run 2538: Runtime.getRuntime().addShutdownHook(fileCloser); sun.rmi.server Activation.java Activation init 240: Runtime.getRuntime().addShutdownHook(shutdownHook); sun.tools.jstat

sun.awt.shell Win32ShellFolderManager2.java Win32ShellFolderManager2 ComInvoker ComInvoker <anonymous java.security.PrivilegedAction<java.lang.Void>> run 493: Runtime.getRuntime().addShutdownHook( sun.awt.windows WToolkit.java WToolkit registerShutdownHook <anonymous java.security.PrivilegedAction<java.lang.Void>> run 285: Runtime.getRuntime().addShutdownHook(shutdown); sun.java2d.d3d D3DScreenUpdateManager.java D3DScreenUpdateManager D3DScreenUpdateManager run 112: Runtime.getRuntime().addShutdownHook(shutdown); java.util.prefs FileSystemPreferences.java FileSystemPreferences <anonymous java.security.PrivilegedAction<java.lang.Void>> run 439: Runtime.getRuntime().addShutdownHook(new Thread() { sun.awt.X11 XToolkit.java XToolkit init <anonymous java.security.PrivilegedAction<java.lang.Void>> run 350: Runtime.getRuntime().addShutdownHook(shutdownThread); sun.awt X11GraphicsDevice.java X11GraphicsDevice setDisplayMode <anonymous java.security.PrivilegedAction<java.lang.Void>> run 445: Runtime.getRuntime().addShutdownHook(t); java.util.prefs MacOSXPreferencesFile.java MacOSXPreferencesFile timer 356: Runtime.getRuntime().addShutdownHook(flushThread); sun.font CFontManager.java CFontManager createFont2D <anonymous java.security.PrivilegedAction<java.lang.Object>> run 232: Runtime.getRuntime().addShutdownHook(fileCloser); sun.lwawt LWToolkit.java LWToolkit init 83: Runtime.getRuntime().addShutdownHook(

I hope that these hooks are already supporting concurrency execution (awt ?) but someone should check if there is no dependencies between them (like systemd or rc scripts does).

PS: As shutdown hooks are given by the application as Thread class instances, I suspect also a possible classloader leak ? In Java web start environment, it may be the cause of my problems as I do not know if the hook thread is still within the application class loader ...

Laurent Bourgès



More information about the core-libs-dev mailing list