这与这两个帖子有关:
基本上,H2 保持对数据库的锁定,即使所有连接都已关闭,因此在停止 Tomcat 时它会挂起等待线程,进程仍在运行。我设法让 H2 不锁定数据库的唯一方法是发出语句SHUTDOWN IMMEDIATELY
命令(香草或compact
没有释放锁定)。
这是在 contextDestroyed 中的 ServletContextListener 类中执行的(我省略了注释和日志行):
ServletContext ctx = servletContextEvent.getServletContext();
DataSource closeDS = databaseConnection.getDatasource();
Connection closeConn = null;
PreparedStatement closePS = null;
try {
closeConn = closeDS.getConnection();
closePS = closeConn.prepareStatement("SHUTDOWN IMMEDIATELY");
closePS.execute();
} catch (Exception ex) {
} finally {
if (closePS != null) {
try { closePS.close(); } catch (SQLException ex) {}
}
if (closeConn != null) {
try { closeConn.close(); } catch (SQLException ex) {}
}
}
try {
databaseConnection.close();
databaseConnection = null;
ctx.setAttribute("databaseConnection", null);
} catch(Exception e) {
}
Enumeration<Driver> drivers = DriverManager.getDrivers();
while (drivers.hasMoreElements()) {
Driver driver = drivers.nextElement();
try {
DriverManager.deregisterDriver(driver);
} catch (Exception e) {
}
}
现在锁被释放 Tomcat 停止(虽然我仍然在日志中收到严重的内存泄漏消息)但现在我在日志中也收到了一些错误堆栈,因此:
INFO: Illegal access: this web application instance has been stopped already.
Could not load java.lang.ThreadGroup.
The eventual following stack trace is caused by an error thrown
for debugging purposes as well as to attempt to terminate
the thread which caused the illegal access, and has no functional impact.
java.lang.IllegalStateException
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1531)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1491)
at org.h2.engine.DatabaseCloser.reset(DatabaseCloser.java:43)
at org.h2.engine.Database.close(Database.java:1155)
at org.h2.engine.DatabaseCloser.run(DatabaseCloser.java:80)
10-sep-2013 13:31:41 org.apache.catalina.loader.WebappClassLoader loadClass
问题是:如何在不导致非法状态异常的情况下关闭数据库。我的代码调用关机命令有问题吗?为什么 H2 会出现这样的问题?JBoss 或 Websphere 没有这个问题,其中应用程序也使用容器提供的数据源运行。