网络应用程序[]似乎启动了一个名为[Abandoned connection cleanup thread]的线程com.mysql.jdbc.AbandonedConnectionCleanupThread。

33
在我进行网页开发的过程中,我突然在Eclipse IDE中关闭了我的网页应用程序。大约一分钟后,我在Eclipse控制台中看到了一个警告
WARNING: The web application [/Spring.MVC] 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.
Sep 06, 2014 8:31:55 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
WARNING: The web application [/Spring.MVC] appears to have started a thread named [Abandoned connection cleanup thread] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
 java.lang.Object.wait(Native Method)
 java.lang.ref.ReferenceQueue.remove(Unknown Source)
 com.mysql.jdbc.AbandonedConnectionCleanupThread.run(AbandonedConnectionCleanupThread.java:40)
Sep 06, 2014 8:32:00 PM org.apache.catalina.core.ApplicationContext log
INFO: No Spring WebApplicationInitializer types detected on classpath
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Sep 06, 2014 8:32:00 PM org.apache.catalina.core.ApplicationContext log
INFO: Initializing Spring root WebApplicationContext
Sep 06, 2014 8:32:03 PM org.hibernate.jpa.internal.util.LogHelper logPersistenceUnitInformation
INFO: HHH000204: Processing PersistenceUnitInfo [
    name: personPU
    ...]

到目前为止,它没有引起任何内存泄漏,我检查了我的VisualVM,一切都像往常一样,但是当我搜索更多关于这个问题的信息时,我意识到这个警告是由于MySQL驱动程序未释放资源或未正确关闭(我不知道如何准确地表达),然后我在SO上找到了这篇相关的文章。

而且,楼主是对的,"不用担心"的答案是不够的。这个警告让我烦恼,因为它可能会给我带来一些未来的持久性问题,这让我非常担心。我尝试了楼主编写的代码,但我遇到了一个问题:应该使用什么库使这段代码正常工作。这是我到目前为止的进展。

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 javax.servlet.annotation.WebListener;
import org.hibernate.annotations.common.util.impl.LoggerFactory;
import com.mysql.jdbc.AbandonedConnectionCleanupThread;
@WebListener
public class ContextFinalizer implements ServletContextListener {

private static final Logger LOGGER = LoggerFactory.getLogger(ContextFinalizer.class);

public void contextInitialized(ServletContextEvent sce) {
}

public void contextDestroyed(ServletContextEvent sce) {
    Enumeration<Driver> drivers = DriverManager.getDrivers();
    Driver d = null;
    while (drivers.hasMoreElements()) {
        try {
            d = drivers.nextElement();
            DriverManager.deregisterDriver(d);
            LOGGER.warn(String.format("Driver %s deregistered", d));
        }
        catch (SQLException ex) {
            LOGGER.warn(String.format("Error deregistering driver %s", d), ex);
        }
    }
    try {
        AbandonedConnectionCleanupThread.shutdown();
    }
    catch (InterruptedException e) {
        logger.warn("SEVERE problem cleaning up: " + e.getMessage());
        e.printStackTrace();
    }
  }
}

我想知道我需要哪些库或者我是否正在使用正确的库来正确地实现这个项目,我甚至不知道应该使用什么日志记录器,感谢任何帮助。


1
记录器对解决方案并不是必需的。你运行了代码吗?发生了什么?你还能看到警告吗? - Sotirios Delimanolis
谢谢您的回复,我无法运行它,我不知道记录器对于这段代码来说是不必要的,我只是在尝试之前重新启动了我的计算机,如果有什么不同的情况发生,我会再次发布。谢谢。 :) - Jeff
@SotiriosDelimanolis,我刚刚试了上面的示例代码,没有记录器(谢谢),是的,它正在工作,AbandonedConnectionCleanupThread正在关闭,但是,当我在我的VisualVM中监视服务器时,permgen空间仍然被占用,我仍然会遇到内存泄漏问题,我仍然需要执行手动GC。但是就代码而言,它确实有效。 - Jeff
4个回答

32

请参考这个答案。看起来MySQL驱动程序应该放在{$TOMCAT]/lib目录下,供多个应用程序共享。请确保您没有将其与每个应用程序一起包含。至少对我而言有效,并且我已经成功消除了警告。

如果您使用Maven,请将依赖项标记为provided。


更新:
问题的根本原因是Tomcat在单例注册表中处理多个应用程序共享的驱动程序时存在垃圾回收问题。关闭一个应用程序无法使Tomcat释放驱动程序。请参考这个答案


1
有人能够再详细解释一下吗?这是与特定的JDBC驱动程序版本相关的错误吗? - Kerem
1
你是否已经将MySQL驱动程序添加到你的Tomcat库中? - borjab
@borjab 不是的,我误解了 provided。现在已添加。但它在 ContextDestroyed 上显示 AbandonedConnectionCleanup..。在 pom.xml 中为 mysql-connector 使用了 provided 作用域。 - Ramanujan R
@borjab 是的。apache-tomcat-8.0.37\lib\mysql-connector-java-5.1.33.jar - Ramanujan R
我在我的pom.xml中包含了<scope>provided</scope>,但是我得到了这个异常ERROR: org.hibernate.engine.jdbc.spi.SqlExceptionHelper - Cannot load JDBC driver class 'com.mysql.cj.jdbc.Driver'。我正在使用hibernate5,所以使用这个驱动程序。 - Suresh
显示剩余5条评论

1
对于我来说,我停止了MySQL(service mysql start),然后停止了bin文件夹中的Tomcat(./shutdown.sh),问题得到了解决。

0
我修复了以下命令运行时的错误:
systemctl status tomcat10.service 它显示了具体的错误内容。
附注:我使用的是Debian操作系统,MariaDb和Tomcat10。

-5

这对我有效

在我的情况下,问题出在 ElasticSearch 上。

从 Postman 发送一个 DELETE 请求到以下端点,并重新启动您的应用程序。

http://localhost:9200/*

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接