Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I need to list the hooks registered with java.lang.ApplicationShutdownHooks

I have a 3rd party application that has a bug which causes it to register multiple shutdown hooks when it only needs 1.

My question is how do I see what the registered shutdown hooks are? I want to iterate them and then call the remove method. The collection holding the hooks is private static and doesn't contain an accessor. We've tried reflection but since the class is package private we have to make our cracker part of java.lang which is a prohibited package.

Any ideas?

/*
 * %W% %E%
 *
 * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
class ApplicationShutdownHooks {
static {
    Shutdown.add(1 /* shutdown hook invocation order */,
        new Runnable() {
            public void run() {
                runHooks();
            }
        });
}

/* The set of registered hooks */
private static IdentityHashMap<Thread, Thread> hooks = new IdentityHashMap<Thread, Thread>();

private void ApplicationShutdownHooks() {}

/* Add a new shutdown hook.  Checks the shutdown state and the hook itself,
 * but does not do any security checks.
 */
static synchronized void add(Thread hook) {
if(hooks == null)
    throw new IllegalStateException("Shutdown in progress");

if (hook.isAlive())
    throw new IllegalArgumentException("Hook already running");

if (hooks.containsKey(hook))
    throw new IllegalArgumentException("Hook previously registered");

    hooks.put(hook, hook);
}

/* Remove a previously-registered hook.  Like the add method, this method
 * does not do any security checks.
 */
static synchronized boolean remove(Thread hook) {
if(hooks == null)
    throw new IllegalStateException("Shutdown in progress");

if (hook == null) 
    throw new NullPointerException();

return hooks.remove(hook) != null;
}

/* Iterates over all application hooks creating a new thread for each
 * to run in. Hooks are run concurrently and this method waits for 
 * them to finish.
 */
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) { }
}
}
}
like image 656
Preston Avatar asked Jul 28 '11 20:07

Preston


People also ask

How do you run a shutdown hook?

Also, when the operating system is shut down or the user presses the ctrl + c the shutdown hooks are invoked. Before completion, the shutdown hooks can be stopped forcefully: It is a special case of the above discussed point.

What is Java shutdown hook?

Shutdown Hooks are a special construct that allows developers to plug in a piece of code to be executed when the JVM is shutting down. This comes in handy in cases where we need to do special clean up operations in case the VM is shutting down.

What is hook in Java?

lang. Runtime. addShutdownHook(Thread hook) method registers a new virtual-machine shutdown hook. The Java virtual machine shuts down in response to two kinds of events. The program exits normally, when the last non-daemon thread exits or when the exit (equivalently, System.exit) method is invoked, or.

How do you install a shutdown hook in a spring boot?

Each SpringApplication will register a shutdown hook with the JVM to ensure that the ApplicationContext is closed gracefully on exit. All the standard Spring lifecycle callbacks (such as the DisposableBean interface, or the @PreDestroy annotation) can be used. In addition, beans may implement the org. springframework.


1 Answers

Package private shouldn't slow you down, this is Reflection! All sorts of voodoo magic are allowed.

In this case, you need to get the class, then the field, then set it to accessible, then read its value.

    Class clazz = Class.forName("java.lang.ApplicationShutdownHooks");
    Field field = clazz.getDeclaredField("hooks");
    field.setAccessible(true);
    Object hooks = field.get(null);
    System.out.println(hooks); //hooks is a Map<Thread, Thread>

A simpler way to view this sort of information might just be to take a heap dump of the application and analyze it in a memory analyzer like MAT (for Eclipse) or JProfiler.

like image 151
Mark Peters Avatar answered Sep 28 '22 06:09

Mark Peters