Spring mvc web应用程序[]注册了JDBC驱动程序[com.mysql.JDBC.driver],但在web应用程序停止时未能注销它

Spring mvc web应用程序[]注册了JDBC驱动程序[com.mysql.JDBC.driver],但在web应用程序停止时未能注销它,spring-mvc,tomcat,spring-security,Spring Mvc,Tomcat,Spring Security,我在stackoverflow上很少看到类似的问题,但我不知道如何解决我的问题。将Spring安全性添加到我的Spring MVC项目后,我得到了以下异常: Jul 20, 2014 3:18:04 PM org.apache.catalina.loader.WebappClassLoader clearReferencesJdbc SEVERE: The web application [] registered the JDBC driver [com.mysql.jdbc.Driver]

我在stackoverflow上很少看到类似的问题,但我不知道如何解决我的问题。将Spring安全性添加到我的Spring MVC项目后,我得到了以下异常:

Jul 20, 2014 3:18:04 PM org.apache.catalina.loader.WebappClassLoader clearReferencesJdbc
SEVERE: The web application [] registered the JDBC driver [com.mysql.jdbc.Driver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
这是我在pom.xml文件中的mysql连接器

    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.31</version>
    </dependency>
和汇编程序

 @Service("assembler")

public class UserAssembler {

@Autowired
private UserDAO userDAO;

@Transactional(readOnly = true)
public User buildUserFromUser(net.viralpatel.contact.model.User user) {
    String role = "ROLE_USER";//userEntityDAO.getRoleFromUserEntity(userEntity);

    Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
    authorities.add(new GrantedAuthorityImpl(role));

    return new User(user.getLogin(), user.getPassword(), true, true, true, true,  authorities);
}
}

您的应用程序没有缺陷。这是JDBC的设计。当webapp首次创建数据库连接时,JDBC驱动程序将被加载并注册

这意味着驱动程序是用web应用程序类加载器加载的。在取消部署时,驱动程序不会被取消注册,这反过来会阻止您的webapp类从GC中删除。这实际上造成了内存泄漏

为了防止这种特殊的内存泄漏,您应该编辑您的
tomcat/conf/server.xml
并进行更改

<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />


  • 对于mysql-connector-java-8.0.x,请改用
    com.mysql.cj.jdbc.NonRegisteringDriver
从webapp工件中排除JDBC驱动程序,并将其放入
tomcat/lib
目录。 现在JDBC驱动程序在启动时由Tomcat加载,并且没有链接到任何webapps类加载程序

为什么要修改server.xml?

另一个内存泄漏是由于MySQL的“放弃连接清理线程”造成的。此线程从第一个请求开始,并保存对webapp类加载器的引用。使用
classesToInitialize
也可以防止内存泄漏

参考资料:

  • tomcat doc v7.0
  • v5.1.41中的注释
  • 源代码v5.1
  • 源代码v8.0
  • v8.0中的变化

我所做的只是把
mysql-connector-java-5.1.31-bin.jar
放在
$CATALINA_HOME/lib
中。没有修改
server.xml

不幸的是,我遇到了新的错误,请看一下我上面编辑的问题,我尝试将mysql-connector-java-5.1.31-bin.jar放入我的/tomcat/lib文件夹,但没有任何帮助。忘了提到驱动程序应该放在tomcat/lib中。更新了我的答案。ClassNotFoundException很奇怪!我检查了mysql-connector-java-5.1.31-bin.jar中是否有未注册的驱动程序。类存在于jar中!你说得对@titi wangsa bin dammore。但MySQL的JDBC驱动程序还有另一个内存泄漏的根源:废弃的连接清理线程。更新了我的答案以反映。可能重复
<beans:bean id="webexpressionHandler" class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler" />

<http auto-config="true">
    <intercept-url pattern="/account/*" access="ROLE_ADMIN" />
    <form-login login-page="/login" default-target-url="/account/overview" authentication-failure-url="/login?error=true"/>
    <remember-me/>
</http>

<beans:bean id="myUserDetailsService" class="net.viralpatel.contact.service.UserDetailsServiceImpl" />


<authentication-manager alias="authenticationManager">
    <authentication-provider user-service-ref="myUserDetailsService" />
</authentication-manager>
INFO: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: /opt/idea-IU-135.909/bin::/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
Jul 20, 2014 3:58:36 PM org.apache.catalina.core.JreMemoryLeakPreventionListener lifecycleEvent
SEVERE: Failed to load class com.mysql.jdbc.NonRegisteringDriver during Tomcat start to prevent possible memory leaks.
java.lang.ClassNotFoundException: com.mysql.jdbc.NonRegisteringDriver
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener 
className="org.apache.catalina.core.JreMemoryLeakPreventionListener"
classesToInitialize="com.mysql.jdbc.NonRegisteringDriver" />