Conflicts between JVM application and j.u.l logging shutdown hooks
David M. Lloyd
david.lloyd at redhat.com
Mon Dec 9 18:22:32 UTC 2013
Given that this issue has existed (and been known) since 1.4, I doubt
anyone is particularly inclined to fix it. The most common workaround I
know of is to simply use or create a LogManager that implements reset()
as a no-op. Just subclassing the built-in LogManager is sufficient to
do this.
On 12/09/2013 11:59 AM, Laurent Bourgès wrote:
> 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
--
- DML
More information about the core-libs-dev
mailing list