当我运行我的web应用程序时,我得到这条消息。它运行良好,但我在关机期间收到这条消息。
严重:web应用程序注册了JBDC驱动程序[oracle.jdbc.driver. exe]。但是当web应用程序停止时,无法注销它。为了防止内存泄漏,JDBC驱动程序已被强制注销。
感谢任何帮助。
当我运行我的web应用程序时,我得到这条消息。它运行良好,但我在关机期间收到这条消息。
严重:web应用程序注册了JBDC驱动程序[oracle.jdbc.driver. exe]。但是当web应用程序停止时,无法注销它。为了防止内存泄漏,JDBC驱动程序已被强制注销。
感谢任何帮助。
当前回答
我经常看到这个问题。是的,Tomcat 7会自动注销它,但这真的能控制你的代码吗?这是一个好的编码实践吗?当然,您希望知道您已经准备好了关闭所有对象、关闭数据库连接池线程和消除所有警告所需的所有正确代码。我当然喜欢。
我就是这么做的。
步骤1:注册监听器
web . xml
<listener>
<listener-class>com.mysite.MySpecialListener</listener-class>
</listener>
步骤2:实现监听器
com.mysite.MySpecialListener.java
public class MySpecialListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
// On Application Startup, please…
// Usually I'll make a singleton in here, set up my pool, etc.
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
// On Application Shutdown, please…
// 1. Go fetch that DataSource
Context initContext = new InitialContext();
Context envContext = (Context)initContext.lookup("java:/comp/env");
DataSource datasource = (DataSource)envContext.lookup("jdbc/database");
// 2. Deregister Driver
try {
java.sql.Driver mySqlDriver = DriverManager.getDriver("jdbc:mysql://localhost:3306/");
DriverManager.deregisterDriver(mySqlDriver);
} catch (SQLException ex) {
logger.info("Could not deregister driver:".concat(ex.getMessage()));
}
// 3. For added safety, remove the reference to dataSource for GC to enjoy.
dataSource = null;
}
}
请随意评论和/或添加…
其他回答
我发现实现一个简单的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");
}
在你的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);
}
}
从版本6.0.24开始,Tomcat附带了内存泄漏检测特性,当web应用程序的/WEB-INF/lib中有JDBC 4.0兼容的驱动程序时,该驱动程序会在web应用程序启动期间使用ServiceLoader API自动注册自己,但在web应用程序关闭期间不会自动注销自己,这会导致此类警告消息。此消息完全是非正式的,Tomcat已经采取了相应的内存泄漏预防操作。
你能做什么?
Ignore those warnings. Tomcat is doing its job right. The actual bug is in someone else's code (the JDBC driver in question), not in yours. Be happy that Tomcat did its job properly and wait until the JDBC driver vendor get it fixed so that you can upgrade the driver. On the other hand, you aren't supposed to drop a JDBC driver in webapp's /WEB-INF/lib, but only in server's /lib. If you still keep it in webapp's /WEB-INF/lib, then you should manually register and deregister it using a ServletContextListener. Downgrade to Tomcat 6.0.23 or older so that you will not be bothered with those warnings. But it will silently keep leaking memory. Not sure if that's good to know after all. Those kind of memory leaks are one of the major causes behind OutOfMemoryError issues during Tomcat hotdeployments. Move the JDBC driver to Tomcat's /lib folder and have a connection pooled datasource to manage the driver. Note that Tomcat's builtin DBCP does not deregister drivers properly on close. See also bug DBCP-322 which is closed as WONTFIX. You would rather like to replace DBCP by another connection pool which is doing its job better then DBCP. For example HikariCP or perhaps Tomcat JDBC Pool.
我在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文件。
谢谢。
我也遇到了类似的问题,但除此之外,每当我在运行Tomcat服务器的情况下修改/保存JSP页面时,我都会得到一个Java堆空间错误,因此上下文没有完全充电。
我的版本是Apache Tomcat 6.0.29和JDK 6u12。
根据URL http://wiki.apache.org/tomcat/MemoryLeakProtection的参考部分的建议,将JDK升级到6u21解决了Java堆空间问题(上下文现在重新加载OK),尽管仍然出现JDBC驱动程序错误。