Tomcat 9 错误 - mysql-cj-abandoned-connection-cleanup [英] Tomcat 9 error - mysql-cj-abandoned-connection-cleanup

查看:758
本文介绍了Tomcat 9 错误 - mysql-cj-abandoned-connection-cleanup的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个在 Tomcat 9 中运行的程序.

I have a program that running in Tomcat 9.

当我重新启动问题时,它显示了上面的警告:

When I restarted the problem, it shows the above warning:

05-Feb-2021 09:48:34.211 WARNING [Thread-5] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [AWSApps] appears to have started a thread named [mysql-cj-abandoned-connection-cleanup] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
 org.apache.catalina.loader.WebappClassLoaderBase.trackLastModified(WebappClassLoaderBase.java:963)
 org.apache.catalina.loader.WebappClassLoaderBase.findResource(WebappClassLoaderBase.java:941)
 org.apache.catalina.loader.WebappClassLoaderBase.getResource(WebappClassLoaderBase.java:1057)
 com.mysql.cj.jdbc.AbandonedConnectionCleanupThread.checkThreadContextClassLoader(AbandonedConnectionCleanupThread.java:117)
 com.mysql.cj.jdbc.AbandonedConnectionCleanupThread.run(AbandonedConnectionCleanupThread.java:84)
 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
 java.lang.Thread.run(Thread.java:748)

Tomcat 版本:Tomcat 9JVM:java-8-openjdk-amd64mysql驱动:mysql-connector-java-8.0.20

Tomcat Version : Tomcat 9 JVM : java-8-openjdk-amd64 Mysql Driver : mysql-connector-java-8.0.20

server.xml

 driverClassName="com.mysql.jdbc.Driver"

我已尝试将 server.xml 更改为

I have tried to change the server.xml into

com.mysql.cj.jdbc.Driver

但是在 Catalina.out 中仍然有警告.

But there is still warning in Catalina.out.

是否有解决问题的指南?

Is there any guide to solve the issue?

谢谢.

推荐答案

如果您的 Web 应用程序在 WEB-INF/lib 文件夹中有 MySQL JDBC 驱动程序的副本,则特殊的 类加载器的委托规则 将选择 Web 应用程序的副本驱动程序而不是全局驱动程序.

If your web application has a copy of the MySQL JDBC driver in the WEB-INF/lib folder, the special delegation rules for classloaders used in Tomcat will select the web application's copy of the driver instead of the global one.

这将在引导类加载器中对应用程序的类加载器创建两个引用:

That will create two references on your application's classloader in the bootstrap classloader:

  • 驱动程序将注册到 DriverManager(在引导类加载器中),
  • 驱动程序将创建一个新线程,并将 ContextClassLoader 设置为 webapp 类加载器.
  • The driver will be registered with DriverManager (in the bootstrap classloader),
  • The driver will create a new thread with the ContextClassLoader set to the webapp classloader.

两个引用都会造成内存泄漏.

Both references can create a memory leak.

备注:即使您不直接使用 DriverManager,而是使用某些数据库池库(将在其中使用 DriverManager最后)或者如果您在 中定义了 JNDI .只有在 中定义的 不受影响.

Remark: This happens even if you don't use a DriverManager directly, but some database pooling library (which will use DriverManager in the end) or if you define a JNDI <Resource> in your <Context>. Only the case of a <Resource> defined in the <GlobalNamingResources> is not affected.

要解决问题,您可以:

  • 从您的 WEB-INF/lib 目录中删除数据库驱动程序,
  • 在应用程序停止时通过调用 DriverManager.deregister 来撤销这些更改,例如在 ServletContextListener 中:
  • either remove the database driver from your WEB-INF/lib directory,
  • reverse these changes when the application stops by calling DriverManager.deregister, e.g. in a ServletContextListener:
public class JdbcDriverListener implements ServletContextListener {

   /**
    * Deregisters the JDBC drivers distributed with the application.
    */
   @Override
   public void contextDestroyed(ServletContextEvent event) {
      final ClassLoader cl = event.getServletContext().getClassLoader();
      final Enumeration<Driver> drivers = DriverManager.getDrivers();
      while (drivers.hasMoreElements()) {
         final Driver driver = drivers.nextElement();
         // We deregister only the classes loaded by this application's classloader
         if (driver.getClass().getClassLoader() == cl) {
            try {
               DriverManager.deregisterDriver(driver);
            } catch (SQLException e) {
               event.getServletContext().log("JDBC Driver deregistration failure.", e);
            }
         }
      }
   }

   /**
    * Registers the JDBC drivers distributed with the application.
    */
   @Override
   public void contextInitialized(ServletContextEvent event) {
      Iterator<@NonNull Driver> driversIterator = ServiceLoader.load(Driver.class).iterator();
      while (driversIterator.hasNext()) {
         try {
            // Instantiates the driver
            driversIterator.next();
         } catch (Throwable t) {
            event.getServletContext().log("JDBC Driver registration failure.", t);
         }
      }
   }
}

我将评论中的信息合并到答案中.

I merge the information from the comments into the answer.

这篇关于Tomcat 9 错误 - mysql-cj-abandoned-connection-cleanup的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆