首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Tomcat 9错误-mysql-cj-废弃-连接-清理

Tomcat 9错误-mysql-cj-废弃-连接-清理
EN

Stack Overflow用户
提问于 2021-02-05 02:21:58
回答 1查看 8.3K关注 0票数 2

我有一个在Tomcat 9上运行的程序。

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

代码语言:javascript
复制
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 9 JVM : java-8-openjdk-amd64 64 Mysql驱动程序:mysql-连接器-java-8.0.20

server.xml

代码语言:javascript
复制
 driverClassName="com.mysql.jdbc.Driver"

我试着把server.xml改成

代码语言:javascript
复制
com.mysql.cj.jdbc.Driver

但在Catalina.out中仍然存在警告。

有解决这个问题的指南吗?

谢谢。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-02-05 07:23:57

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

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

  • 驱动程序将注册到DriverManager (在引导类加载程序中),
  • 驱动程序将创建一个新线程,将ContextClassLoader设置为webapp类加载器。

这两个引用都可以创建内存泄漏。

备注:即使不直接使用DriverManager,但某些数据库池库(最终将使用DriverManager )或在<Context>中定义JNDI <Resource>,也会发生JNDI。只有在<Resource>中定义的<GlobalNamingResources>的情况不受影响。

要解决这个问题,您可以:

  • 要么从WEB-INF/lib目录中删除数据库驱动程序,
  • 当应用程序停止时,通过调用DriverManager.deregister (例如在ServletContextListener中)来逆转这些更改:
代码语言:javascript
复制
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);
         }
      }
   }
}

编辑:,我将注释中的信息合并到答案中。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66056707

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档