I maintain a JDBC driver that also has an embedded database server mode provided through a native library, which is accessed through JNA. The shutdown process, done as part of unloading the native library itself, runs into problems on Windows due to the order of unloading its dependencies. To avoid access violations or other issues, I need to explicitly shut down the embedded engine before unloading this library.
Due to the nature of its use, it is difficult to determine an appropriate moment to call for a shutdown. The only correct way to do this for a normal Java application is by registering a shutdown hook using
Runtime.getRuntime().addShutdownHook
with a subclass of Thread
that implements the shutdown logic.
This works fine for a normal Java application, but for web applications that include my library as part of the application (in the WEB-INF/lib
of the WAR), this will cause a memory leak on undeploy as the shutdown hook will maintain a strong reference to my shutdown implementation and to the classloader of the web application.
What would be a suitable and appropriate way to address this? Options I'm looking into right now are:
Using
java.sql.DriverAction.deregister()
to do the cleanup.Not suitable as a driver will not be deregistered on a normal application exit.
Using
java.sql.DriverAction.deregister()
to remove the shutdown hook and execute the shutdown logic itself.Use of
DriverAction
is slightly problematic given the driver still supports Java 7, and this class was introduced in JDBC 4.2 (Java 8). This is technically not always the correct use of action (a JDBC driver can also be deregistered while existing connections remain valid and in use), and it is possible that the driver is used (through ajavax.sql.DataSource
) while the JDBCjava.sql.Driver
implementation is not registered.Including a
javax.servlet.ServletContextListener
implementation annotated with@WebListener
with the driver that will remove the shutdown hook and execute the shutdown logic itself.This option has complications if the driver is deployed to the server as a whole instead of to a specific web application (although those complications can be solved).
Is there a shutdown mechanism in Java I have overlooked that could be suitable for my needs?
@WebListener
-based solution in Tomcat to deregister a fewjava.sql.Driver
s (usingDriverManager.deregisterDriver
) in a few containers (I always deregister exactly the driver that got registered by given container by storingClass<? extends java.sql.Driver>
), and I'm wondering whether I haven't overlooked something. – Danialah<catalina-home>/lib
and define a data source in server.xml. Similar features exist in other application servers. Manually registering/deregistering the driver won't work for those situations (nor will this work for non-web applications), and I don't think it will solve my problem if the driver is globally available even if registered per WAR (java.sql.Driver
implementations are (or should be) pretty light-weight). – Fogle