Conflicts between JVM application and j.u.l logging shutdown hooks

Laurent Bourgès bourges.laurent at gmail.com
Mon Dec 9 17:59:26 UTC 2013


Anybody wants to look at this logging issue I reported several months ago?

Le 27 juin 2013 11:57, "Laurent Bourgès" <bourges.laurent at gmail.com> a
écrit :
>
> 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<Thread> 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
> <anonymous java.security.PrivilegedAction>
> 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
> <anonymous java.security.PrivilegedAction>
> 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
> <anonymous java.security.PrivilegedAction>
> 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