当我运行我的web应用程序时,我得到这条消息。它运行良好,但我在关机期间收到这条消息。
严重:web应用程序注册了JBDC驱动程序[oracle.jdbc.driver. exe]。但是当web应用程序停止时,无法注销它。为了防止内存泄漏,JDBC驱动程序已被强制注销。
感谢任何帮助。
当我运行我的web应用程序时,我得到这条消息。它运行良好,但我在关机期间收到这条消息。
严重:web应用程序注册了JBDC驱动程序[oracle.jdbc.driver. exe]。但是当web应用程序停止时,无法注销它。为了防止内存泄漏,JDBC驱动程序已被强制注销。
感谢任何帮助。
当前回答
在你的servlet上下文监听器contextDestroyed()方法中,手动注销驱动程序:
// This manually deregisters JDBC driver, which prevents Tomcat 7 from complaining about memory leaks wrto this class
Enumeration<Driver> drivers = DriverManager.getDrivers();
while (drivers.hasMoreElements()) {
Driver driver = drivers.nextElement();
try {
DriverManager.deregisterDriver(driver);
LOG.log(Level.INFO, String.format("deregistering jdbc driver: %s", driver));
} catch (SQLException e) {
LOG.log(Level.SEVERE, String.format("Error deregistering driver %s", driver), e);
}
}
其他回答
我发现实现一个简单的destroy()方法来注销任何JDBC驱动程序工作得很好。
/**
* Destroys the servlet cleanly by unloading JDBC drivers.
*
* @see javax.servlet.GenericServlet#destroy()
*/
public void destroy() {
String prefix = getClass().getSimpleName() +" destroy() ";
ServletContext ctx = getServletContext();
try {
Enumeration<Driver> drivers = DriverManager.getDrivers();
while(drivers.hasMoreElements()) {
DriverManager.deregisterDriver(drivers.nextElement());
}
} catch(Exception e) {
ctx.log(prefix + "Exception caught while deregistering JDBC drivers", e);
}
ctx.log(prefix + "complete");
}
这个错误发生在我使用JTDS Driver 1.3.0 (SQL Server)的Grails应用程序中。问题是SQL Server登录错误。解决这个问题后(在SQL Server),我的应用程序被正确部署在Tomcat。提示:我在stacktrace.log中看到了错误
我在AWS上部署Grails应用程序时遇到过这个问题。这是JDBC默认驱动程序的问题。H2驱动。 正如你在数据源中看到的那样。配置文件夹中的Groovy。如下图所示:
dataSource {
pooled = true
jmxExport = true
driverClassName = "org.h2.Driver" // make this one comment
username = "sa"
password = ""
}
注释那些提到org.h2的行。数据源中的驱动程序。Groovy文件,如果您没有使用该数据库。 否则,您必须下载数据库jar文件。
谢谢。
这纯粹是mysql的驱动程序或tomcats webapp-classloader中的驱动程序注册/注销问题。复制mysql驱动到tomcats lib文件夹(所以它是由jvm直接加载,而不是由tomcat),消息将会消失。这使得mysql jdbc驱动程序只有在JVM关闭时才会被卸载,没有人会关心内存泄漏。
尽管Tomcat会强制注销JDBC驱动程序,但在上下文破坏时清理webapp创建的所有资源是一个很好的实践,以防您移动到另一个servlet容器,该容器不像Tomcat那样执行内存泄漏预防检查。
但是,全面取消司机登记的方法是危险的。DriverManager.getDrivers()方法返回的一些驱动程序可能是由父类加载器(即servlet容器的类加载器)加载的,而不是webapp上下文的类加载器(例如,它们可能在容器的lib文件夹中,而不是webapp的,因此在整个容器中共享)。注销这些将会影响其他可能使用它们的web应用程序(甚至容器本身)。
因此,在取消注册之前,应该检查每个驱动程序的ClassLoader是否是web应用程序的ClassLoader。因此,在你的ContextListener的contextDestroyed()方法中:
public final void contextDestroyed(ServletContextEvent sce) {
// ... First close any background tasks which may be using the DB ...
// ... Then close any DB connection pools ...
// Now deregister JDBC drivers in this context's ClassLoader:
// Get the webapp's ClassLoader
ClassLoader cl = Thread.currentThread().getContextClassLoader();
// Loop through all drivers
Enumeration<Driver> drivers = DriverManager.getDrivers();
while (drivers.hasMoreElements()) {
Driver driver = drivers.nextElement();
if (driver.getClass().getClassLoader() == cl) {
// This driver was registered by the webapp's ClassLoader, so deregister it:
try {
log.info("Deregistering JDBC driver {}", driver);
DriverManager.deregisterDriver(driver);
} catch (SQLException ex) {
log.error("Error deregistering JDBC driver {}", driver, ex);
}
} else {
// driver was not registered by the webapp's ClassLoader and may be in use elsewhere
log.trace("Not deregistering JDBC driver {} as it does not belong to this webapp's ClassLoader", driver);
}
}
}