Browse DevX
Sign up for e-mail newsletters from DevX


Use JVM Shutdown Hooks to Optimize Resources-3 : Page 3




Building the Right Environment to Support AI, Machine Learning and Deep Learning

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 JdbHook.java 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 JdbcHook.java 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.

Mark Watson is a Java consultant and the author of 14 books on Java, artificial intelligence, C++, and intelligent agents. .
Thanks for your registration, follow us on our social networks to keep up-to-date