当我运行我的web应用程序时,我得到这条消息。它运行良好,但我在关机期间收到这条消息。
严重:web应用程序注册了JBDC驱动程序[oracle.jdbc.driver. exe]。但是当web应用程序停止时,无法注销它。为了防止内存泄漏,JDBC驱动程序已被强制注销。
感谢任何帮助。
当我运行我的web应用程序时,我得到这条消息。它运行良好,但我在关机期间收到这条消息。
严重:web应用程序注册了JBDC驱动程序[oracle.jdbc.driver. exe]。但是当web应用程序停止时,无法注销它。为了防止内存泄漏,JDBC驱动程序已被强制注销。
感谢任何帮助。
当前回答
这纯粹是mysql的驱动程序或tomcats webapp-classloader中的驱动程序注册/注销问题。复制mysql驱动到tomcats lib文件夹(所以它是由jvm直接加载,而不是由tomcat),消息将会消失。这使得mysql jdbc驱动程序只有在JVM关闭时才会被卸载,没有人会关心内存泄漏。
其他回答
针对每个应用部署的解决方案
这是一个侦听器,我写来解决这个问题:它自动检测驱动程序是否已经注册自己,并采取相应的行动
重要的是:它只能在驱动程序jar部署在WEB-INF/lib中使用,而不是像许多人建议的那样部署在Tomcat /lib中,这样每个应用程序都可以处理自己的驱动程序并在未受影响的Tomcat上运行。恕我直言,这才是应该的方式。
只需在web.xml中配置侦听器,然后再执行其他操作即可。
在web.xml顶部添加:
<listener>
<listener-class>utils.db.OjdbcDriverRegistrationListener</listener-class>
</listener>
保存为utils/db/OjdbcDriverRegistrationListener.java:
package utils.db;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Enumeration;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import oracle.jdbc.OracleDriver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Registers and unregisters the Oracle JDBC driver.
*
* Use only when the ojdbc jar is deployed inside the webapp (not as an
* appserver lib)
*/
public class OjdbcDriverRegistrationListener implements ServletContextListener {
private static final Logger LOG = LoggerFactory
.getLogger(OjdbcDriverRegistrationListener.class);
private Driver driver = null;
/**
* Registers the Oracle JDBC driver
*/
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
this.driver = new OracleDriver(); // load and instantiate the class
boolean skipRegistration = false;
Enumeration<Driver> drivers = DriverManager.getDrivers();
while (drivers.hasMoreElements()) {
Driver driver = drivers.nextElement();
if (driver instanceof OracleDriver) {
OracleDriver alreadyRegistered = (OracleDriver) driver;
if (alreadyRegistered.getClass() == this.driver.getClass()) {
// same class in the VM already registered itself
skipRegistration = true;
this.driver = alreadyRegistered;
break;
}
}
}
try {
if (!skipRegistration) {
DriverManager.registerDriver(driver);
} else {
LOG.debug("driver was registered automatically");
}
LOG.info(String.format("registered jdbc driver: %s v%d.%d", driver,
driver.getMajorVersion(), driver.getMinorVersion()));
} catch (SQLException e) {
LOG.error(
"Error registering oracle driver: " +
"database connectivity might be unavailable!",
e);
throw new RuntimeException(e);
}
}
/**
* Deregisters JDBC driver
*
* Prevents Tomcat 7 from complaining about memory leaks.
*/
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
if (this.driver != null) {
try {
DriverManager.deregisterDriver(driver);
LOG.info(String.format("deregistering jdbc driver: %s", driver));
} catch (SQLException e) {
LOG.warn(
String.format("Error deregistering driver %s", driver),
e);
}
this.driver = null;
} else {
LOG.warn("No driver to deregister");
}
}
}
我将补充一些我在Spring论坛上发现的东西。如果您将JDBC驱动程序jar移到tomcat lib文件夹,而不是与webapp一起部署它,则警告似乎消失了。我可以确定这对我很有效
http://forum.springsource.org/showthread.php?87335-Failure-to-unregister-the-MySQL-JDBC-Driver&p=334883#post334883
我经常看到这个问题。是的,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;
}
}
请随意评论和/或添加…
如果您从Maven构建的war中获得此消息,则将JDBC驱动程序的作用域更改为已提供,并将其副本放在lib目录中。是这样的:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.18</version>
<!-- put a copy in /usr/share/tomcat7/lib -->
<scope>provided</scope>
</dependency>
我在Tomcat版本6.026中发现了同样的问题。
我在WebAPP库和TOMCAT库中使用Mysql JDBC.jar。
要解决上述问题,请从TOMCAT lib文件夹中删除Jar。
因此,我所理解的是TOMCAT正在正确地处理JDBC内存泄漏。但是如果MYSQL Jdbc jar在WebApp和Tomcat Lib中被复制,Tomcat将只能处理Tomcat Lib文件夹中的jar。