The Source for Java Technology Collaboration
User: Password:



David Walend

David Walend's Blog

Shutdown Hooks

Posted by dwalend on May 09, 2004 at 04:38 PM | Comments (9)

I just handed in my last assignment for my masters degree, completing a ten-year effort. Maybe there is a reason why they put a "Slow Children" sign in front of our house. And JSDK 1.5 is rolling out some time soon. It's a good week for a blog about finishing things -- time for an article about shutdown hooks.

A shutdown hook is a Thread designed to be run after a program receives a signal to exit, but before daemon threads stop, finalizers run, and the JVM goes poof. Shutdown hooks are great for clearing dirty caches, closing out open resources, and announcing this shutdown to other processes.

In 1999 I sent Sun a "request for enhancement" for the equivalent of C's onexit() facility. I was building this funky distributed logging system and needed a way to record cached log messages if someone hit control-C or called System.exit(). The JSDK of the day, 1.2 I suppose, didn't offer me anything beyond runFinalizersOnExit(). I needed to write log messages and flush the system, which I couldn't do reliably if the objects were in the process of dissolving. The team found a hacky way to solve the immediate problem; we added our own way to shut down the system via messaging, and tried to reeducate the rest of the company to use it instead of control-C (but that's another blog).

Sun added the shutdown hook feature in JSDK 1.3, about eighteen months later. RFEs take patience, but make the system better for us all. The company that asked me to build that logging system is long gone, but I've used shutdown hooks on a dozen projects since they were introduced.

Here's a code segment for setting up a shutdown hook to clean out an arbitrary Cache:

...
//A static inner class Runnable.
        private static class CacheCleaner
            implements Runnable
        {
            private Cache cache
            
            private CacheCleaner(Cache cache)
            {
                this.cache = cache;
            }
            
            public void run()
            {
                try
                {
                    cache.clean();
                }
                catch(CacheException ce)
                {
                    Log.IT.log(Level.SEVERE,"Unable to clean cache during shutdown",ce);
                }
            }    
        }
...
//Inside the Cache class:
    private CacheCleaner cleaner = new CacheCleaner(this);

    public Runnable getShutdownRunnable()
    {
        return cleaner;
    }
...

//in setup code somewhere.
        Thread hook = new Thread(cache.getShutdownRunnable());
        Runtime.getRuntime().addShutdownHook(hook);

I like Runnable implementations for my shutdown hooks instead of extending Thread. It keeps the API for my stuff separate from the zoo of methods available for Thread. In the library side of the code, I make the shutdown Runnable accessible so that I can control the order that things shut down from another part of the code. I usually have to customize the shutdown order. It changes via negotiation with the rest of the system. I try to log what's going on if things go wrong; debugging as the system fades away can be frustrating.

Shutdown hooks need to be quick, deadlock-safe and can not start new threads. Read through the JSKD API in the addShutdownHook() method before trying this out.

Night school and RFEs exist on a different time scale. An RFE in the JSDK core kit may take a year or two to sort out, if it's accepted. Before posting an RFE for some core thing, make sure that the only way to add the feature is through the change you are suggesting.

Reading: Chessmen of Mars, Burroughs.
Hearing: La Mort de Cleopatre, Berlioz.


Bookmark blog post: del.icio.us del.icio.us Digg Digg DZone DZone Furl Furl Reddit Reddit
Comments
Comments are listed in date ascending order (oldest first) | Post Comment

  • Shutdown hooks and java.util.logging API
    I have previously used shutdown hook threads to do cleanup and write final log messages for a couple of different daemon-style apps when they were killed.
    However when I swapped over to using the java.util.logging.* APIs for all my logging (to centralize logging configuration apart from anything else) I found my final log messages were not being written to the logging.properties-configured logfile from the shutdown hook thread (or rather, some were and most weren't, in an unpredictable way that seemed to indicate threading problems).
    Apparently the JDK logging API has it's own shutdown hook thread used to cleanup logfiles etc., and since all shutdown hook threads are run in parallel you can't reliably log from a shutdown hook thread (or any method called from it - e.g. my cleanup code) using the JDK1.4 logging API.
    The workarounds I have used are either to use some other logging API or shutdown the application using a message of some sort other than a kill signal, neither of which I particularly like - so if someone else has come up with a better workaround I'd like to hear it. My preference would be to be able to configure the FileLogger to cleanup logging when my code requests it, rather than as part of JDK logging cleanup.

    Posted by: adbaxter on May 10, 2004 at 05:05 AM

  • Shutdown hooks and java.util.logging API
    Looks like someone suggested it at one point. http://developer.java.sun.com/developer/bugParade/bugs/4682478.html , http://developer.java.sun.com/developer/bugParade/bugs/4744270.html and http://developer.java.sun.com/developer/bugParade/bugs/4748132.html .

    (Are those all from you?)

    I'll put in another RFE for exposing the hook and giving us control over it. Probably too late to get it into 1.5, and post a note here so we can get some votes behind it.

    Hope that helps,

    Dave

    Posted by: dwalend on May 10, 2004 at 07:27 AM

  • Be careful!
    Ive had pretty bad experiences with shutdown listeners. Right now, I use them to close my JMS listeners and thats it! And even that I should probably change.

    In the past I've found them to be pretty unreliable. Sometimes they run, when the weather is nice, and things are happy. Other times...

    Anyway. For command line apps, I can see how the CTRL-C thing might be a problem. For UI apps though, you can trap all exit commands and control safe shutdown yourself.

    Word to the wise...

    -jonathan

    Posted by: jonathansimon on May 10, 2004 at 08:18 AM

  • Relevant RFE
    While the shutdown hook API is far better than nothing, it really needs to be enhanced.

    See this RFE for a discussion of some of the other issues.

    Posted by: coxcu on May 10, 2004 at 08:29 AM

  • Shutdown hooks and java.util.logging API
    That's a nice thought, bu I doubt this page will be generating many referral hits six months from now when your new RFE becomes publicly visible.

    Posted by: coxcu on May 10, 2004 at 10:52 AM

  • Shutdown hooks and java.util.logging API
    http://developer.java.sun.com/developer/bugParade/bugs/5036297.html (your own?) seems to do a nice job of explaining things. Its only got one vote right now -- mine. You might want to take a minute to vote on it yourself. Votes seem to keep Sun from just brushing off RFEs they don't want to take on.

    In my experience, bugs show up after a few days, a week if I send one in during the holidays. The real time lag will be waiting for JSDK 1.6.

    Dave

    Posted by: dwalend on May 10, 2004 at 03:34 PM

  • Shutdown hooks and java.util.logging API
    In parallel is not really true on a single CPU machine.

    Does giving your shutdown hook Thread a higher priority help?

    I haven't tried, but it would probably cause your shutdown hook to run before the logging one.

    Unless the logger code specifies a priority for its shutdown thread, it will inherit the priority of the thread that creates it - so you could also temporarily drop the priority while you call the logger API where the shutdown hook is set up - therefore encouraging it to be the last shutdown hook to run. Unless you have at least as many processors as there are shutdown hooks, the shutdown hooks must be scheduled, and changing the priorities can have a pretty strong influence on thread scheduling order.

    Bruce

    Posted by: brucechapman on May 10, 2004 at 04:56 PM

  • Shutdown hooks and java.util.logging API
    The particular application was portable code running on single and multiple processor machines. The API says (with my emphasis)

    When the virtual machine begins its shutdown sequence it will start all registered shutdown hooks in some unspecified order and let them run concurrently.

    Of course concurrently does not necessarily actually mean in parallel, but I would not want to rely on manipulating the thread priority to get reliable and reproducible effects on different architectures (I always want to see my log messages...). Having said that I'll give it a go and see what happens.

    Posted by: adbaxter on May 11, 2004 at 04:45 AM

  • Bug review times
    Yep, I submitted that. Thanks for the vote. I would vote for it, but I only get three votes--just like everybody else, and they are all allocated to a different RFE.

    I think the turnaround time varies based on which review pile the bug ends up in. My records (since I started keeping track due to multi-month review times) indicate that if a bug isn't reviewed within a week, it probably won't be reviewed within 100 days.


    153 days
    dateCreated : 2002-09-06 16:01:59.5
    dateEvaluated : 2003-02-06 12:21:59.402


    131 days
    dateCreated : 2002-09-07 11:14:13.1
    dateEvaluated : 2003-01-16 15:55:28.601


    133 days
    dateCreated : 2003-11-26 10:51:48.2
    dateEvaluated : 2004-04-07 13:38:41.609


    117 days
    dateCreated : 2003-12-27 00:41:28.4
    dateEvaluated : 2004-04-22 15:19:03.78


    50 days
    dateCreated : 2002-11-27 09:21:47.1
    dateEvaluated : 2003-01-16 12:51:54.113


    3 days
    dateCreated : 2004-01-03 18:13:30.0
    dateEvaluated : 2004-04-22 15:45:10.859


    1 day
    dateCreated : 2004-04-11 10:11:26.9
    dateEvaluated : 2004-04-12 10:58:55.390


    0 days

    dateCreated : 2003-02-06 10:06:29.3
    dateEvaluated : 2003-02-06 12:23:32.85

    Posted by: coxcu on May 11, 2004 at 08:18 AM





Powered by
Movable Type 3.01D
 Feed java.net RSS Feeds