Use JVM Shutdown Hooks to Optimize Resources

Use JVM Shutdown Hooks to Optimize Resources

ave you ever found yourself in the following scenario:

  1. You’ve created server-side Java applications for a production environment.
  2. You write a program that allocates external resources: connections to a database using JDBC.
  3. A user prematurely terminates the program (by typing control-C, for example).
  4. The external database server eventually needs to be restarted because all client connections are allocated but not freed.

If this sounds familiar, it’s time to explore a seldom-used feature of the Java Virtual Machine (JVM): the ability to register JVM shutdown hooks that execute before a JVM shuts down. In the above scenario, JVM shutdown hooks could perform cleanup processing to free the external resources. This 10-Minute Solution offers two quick demonstrations (one simple, one more complex) of how to use these hooks in your own Java programs.

In production environments, JVMs are killed and restarted either automatically by network management systems or manually by a network administrator. When a JVM is killed, it is often necessary to perform some cleanup work before the JVM finishes shutting down.

JVM shutdown hooks provide a clean and simple mechanism for registering application-specific behavior that performs cleanup work when a JVM terminates.

A Simple Example: the SimpleHook Class
You implement JVM shutdown hooks using a separate class that extends the Thread class (click here to download the accompanying source code for this Solution). When you register an instance of this separate class with a JVM (you will learn how to do this later), the shutdown thread class starts when the JVM terminates.

The non-public class MyShutdown is defined at the bottom of the file (included in the source code download):

class MyShutdown extends Thread {    public MyShutdown(SimpleHook managedClass) {        super();        this.managedClass = managedClass;    }    private SimpleHook managedClass;    public void run() {        System.out.println("MyShutDown thread started");        try {            managedClass.freeResources();        } catch (Exception ee) {            ee.printStackTrace();        }    }}

Notice that the constructor requires a reference to the managed application class. In the design pattern this Solution (and I) use, the managed parent class is expected to define a method freeResources(). To be tidy, you could define a separate interface that defines the freeResources() method signature and have managed classes implement this interface. However, to keep this example simple, I just concentrate on using JVM shutdown hooks.

The constructor for the managed class SimpleHook creates an instance of the MyShutdown class and registers this instance with the JVM:

    public SimpleHook() {        // set up service termination hook (gets called        // when the JVM terminates from a signal):        MyShutdown sh = new MyShutdown(this);        Runtime.getRuntime().addShutdownHook(sh);    }

See the source file for the complete code.

A More Complex Example: the JdbcHook Class
You now understand how to write JVM shutdown hooks. The slightly more complex example in this section shows a common use for JVM shutdown hooks: freeing external (to the JVM) database connections.

A few years ago, I wrote some Java code and made an error: database connections to my local PostgreSQL database server were not getting closed. After restarting my database server, I noticed the coding error and fixed it. This experience reinforced the importance of using a coding pattern to ensure that database connections get properly closed.

For example, for infrequent database access, the following code pattern works well:

        Connection conn = null;        Statement stmt = null;        try {            conn =              DriverManager.getConnection(DBurl, DBuser,                                                                      DBpassword);            stmt = conn.createStatement();            stmt.executeUpdate("insert into ErrorDB values ('"                          + topic + "', '" +                             error + "', " +                              System.currentTimeMillis() + ", '')");        } catch (Exception ee) {            ee.printStackTrace();        } finally {            if (stmt != null) {                try {                    stmt.close();                } catch (Exception e2) {                }            }            if (conn != null) {                try {                    conn.close();                } catch (Exception e2) {                }            }        }

This coding pattern almost guarantees that external database connection resources will be freed, but it is inappropriate for applications that require frequent database access because of the overhead of repeatedly opening and closing database connections.

A better design pattern is to create a database connection and reuse it. However, you must insure that the database connection eventually gets closed. This is a good use for JVM shutdown hooks!

The example in the file (included in the source code download) is simple enough for me to list most of the code here. First, you define the database connection information:

    private Connection conn = null;    public static String DBurl =  "jdbc:postgresql://localhost:5432/test?user=postgres";    public static String DBdriver =        "org.postgresql.Driver";    static {        /**         * Check to see if parameters are set         * at runtime to override defaults:         */        try {            DBurl = System.getProperty("DBurl", DBurl);            DBdriver = System.getProperty("DBdriver",                                                                      DBdriver);        } catch (Exception ee) {            ee.printStackTrace();        }    }

You hard coded the database connection URL, but check to see if this information is overridden at runtime (e.g., by using a command line argument such as -DDBurl=jdbc:...). The file contains a non-public class MyJdbcConnectionShutdownHook that is almost identical to the class MyShutdown (derived from the Thread class) that you used in the previous section. Look at the source file for details.

The constructor for class JdbcHook registers the shutdown hook class with the JVM:

    public JdbcHook() throws Exception {        Class.forName(DBdriver);        conn = DriverManager.getConnection(DBurl);        // set up service termination hook (gets called        // when the JVM terminates from a signal):        MyJdbcConnectionShutdownHook sh =             new MyJdbcConnectionShutdownHook(this);        Runtime.getRuntime().addShutdownHook(sh);    }

When the JVM terminates, the method freeResources() is called:

    public void freeResources() {        try {            if (conn != null && conn.isClosed()==false) {                conn.close();            }        } catch (Exception ee) {            System.out.println("Error freeing resources: " +                                             ee);            ee.printStackTrace();        }    }

Think Beyond Your Development Environment
As Java developers, we tend to “live” in our development environments, where freeing resources is usually not an issue. However, a proper architecture takes into account the problems that occur when systems must run continually. You should get in the habit of writing all of your Java code as if it will be deployed in a production environment.


About Our Editorial Process

At DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere.

See our full editorial policy.

About Our Journalist