ssm框架——警告:为防止内存泄露,已被强制取消注册
搭建了一个ssm框架项目,使用本机tomcat运行,没有问题,非常顺利,但停止运行时,报出了警告:
警告 [localhost-startStop-1] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesJdbc Web应用程序 [demo] 注册了JDBC驱动程序 [com.alibaba.druid.proxy.DruidDriver],但在Web应用程序停止时无法注销它。 为防止内存泄漏,JDBC驱动程序已被强制取消注册。
警告 [localhost-startStop-1] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesJdbc Web应用程序 [demo] 注册了JDBC驱动程序 [com.microsoft.sqlserver.jdbc.SQLServerDriver],但在Web应用程序停止时无法注销它。 为防止内存泄漏,JDBC驱动程序已被强制取消注册。
经过上下求索,终于得知:
从版本6.0.24开始,Tomcat附带了内存泄漏检测功能,当webapp的
/WEB-INF/lib
中存在JDBC兼容驱动程序时,它会导致出现此类警告消息,该驱动程序在webapp启动期间使用ServiceLoader
API自动注册,但是在webapp关闭期间没有自动注销。这条消息纯粹是非正式的,Tomcat已经相应地采取了内存泄漏防护措施。 你能做什么?
忽略这些警告。
Tomcat正在做好自己的工作。实际的错误是在别人的代码(有问题的JDBC驱动程序)中,而不是在你的代码中。很高兴Tomcat正确地完成了它的工作并等到JDBC驱动程序供应商修复它以便你可以升级驱动程序。
我:???不就是让我不管它???不行,我做不到
最终解决办法:
方法一
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>6.4.0.jre8</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.8</version>
<scope>provided</scope>
</dependency>
- 修改pom.xml文件:添加
<scope>provided</scope>
,这样点击启动后编译出的项目文件的lib中将没有这两个jar包。 - 将这两个包放到本机tomcat的lib文件夹下。
- 运行项目,不再有警告。
方法二
方法二是通过添加实现ServletContextListener的监听器用于关闭对象和数据库连接池线程,但这个方法我还没试
1.在web.xml中添加listener
<listener>
<listener-class>com.mysite.MySpecialListener</listener-class>
</listener>
2.监听器
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) {
AbandonedConnectionCleanupThread.checkedShutdown();
ClassLoader cl = Thread.currentThread().getContextClassLoader();
Enumeration<Driver> drivers = DriverManager.getDrivers();
while (drivers.hasMoreElements()) {
Driver driver = drivers.nextElement();
if (driver.getClass().getClassLoader() == cl) {
try {
System.out.println("Deregistering JDBC driver {}");
DriverManager.deregisterDriver(driver);
} catch (SQLException ex) {
System.out.println("Error deregistering JDBC driver {}");
ex.printStackTrace();
}
} else {
System.out.println("Not deregistering JDBC driver {} as it does not belong to this webapp's ClassLoader");
}
}
}
}