【问题标题】:Started a thread named MultiThreadedHttpConnectionManager cleanup but has failed to stop it启动了一个名为 MultiThreadedHttpConnectionManager cleanup 的线程,但未能停止它
【发布时间】:2011-05-23 15:33:15
【问题描述】:

我正在使用 Amazon Web Services AWS Java SDK 编写一个 Web 应用程序。 Apache commons HttpClient 版本 3 在幕后使用。我已经包含了 commons-httpclient-3.0.1.jar。

我的 catalina.out 中有以下警告

SEVERE: The web application [/MyAppName] appears to have started a thread named
[MultiThreadedHttpConnectionManager cleanup] but has failed to stop it. This is 
very likely to create a memory leak.

所以我写了一个 ServletContextListener 调用 contextDestroyed() 方法:

MultiThreadedHttpConnectionManager.shutdownAll();

但是,尽管调用了该方法,警告仍然显示。我还应该做些什么来确保清理干净?

编辑:我想绝对确定 contextDestroyed() 确实被调用了(根据 nos 的建议),所以我在方法的第一个语句上放置了一个断点,停止了服务器和断点被击中我一步一步地执行该方法以确保没有引发异常,并且该方法的每一行都没有问题地执行。这是我的源代码:

@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
    System.out.println("contextDestroyed() start");
    MyMemCache.shutDown();
    MultiThreadedHttpConnectionManager.shutdownAll();
    ClassLoader contextClassLoader=Thread.currentThread().getContextClassLoader();
    LogFactory.release(contextClassLoader);
    java.beans.Introspector.flushCaches();
    System.out.println("contextDestroyed() end");
}

热插拔时:

INFO: Reloading Context with name [/MyAppName] has started
contextDestroyed() start
contextDestroyed() end
05 24, 11 3:11:00 PM org.apache.catalina.loader.WebappClassLoader 
    clearReferencesThreads
SEVERE: The web application [/MyAppName] appears to have started a thread 
    named [MultiThreadedHttpConnectionManager cleanup] but has failed to 
    stop it. This is very likely to create a memory leak.

【问题讨论】:

  • 你 100% 确定你的 contextDestroyed() 被调用了吗?
  • 把 try catch 放到 contextDestroyed 方法中。
  • 好的,我正在为 Exception 添加一个 try catch,并打印堆栈跟踪。但是,如果引发异常,则不会打印字符串“contextDestroyed() end”。如果有什么被抓到我会更新...
  • 更新是:我添加了try/catch,我继续开发其他东西,经历了许多重新部署,我从未见过该方法抛出异常。
  • 实际上用 MultiThreadedHttpConnectionManager.shutdownAll() 监听;为我做了这项工作。线程正确关闭..

标签: java tomcat amazon-web-services


【解决方案1】:

这是 AWS 开发工具包中的一个错误,他们打开两个 HttpClient 并只关闭其中一个。 我的问题略有不同,因为我想在不重新启动 webapp 的情况下启动和停止各个区域和帐户的客户端。

我已经通过以下方式解决了这个问题(我已向他们报告,但他们似乎不愿意解决):

public class MyAmazonEC2Client extends AmazonEC2AsyncClient {
    private boolean shutdownCalled = false;


    public MyAmazonEC2Client(final AWSCredentials awsCredentials) {
        super(awsCredentials);
    }


    public MyAmazonEC2Client(final AWSCredentials awsCredentials, final ClientConfiguration clientConfiguration) {
        this(awsCredentials, clientConfiguration, Executors.newCachedThreadPool());
    }


    public MyAmazonEC2Client(
                                 final AWSCredentials awsCredentials,
                                 final ClientConfiguration clientConfiguration,
                                 final ExecutorService executor) {
        super(awsCredentials, clientConfiguration, executor);
    }


    /**
     * Shuts down this client object, releasing any resources that might be held open.<br />
     */
    @Override
    public synchronized void shutdown() {
        try {
            shutdownCalled = true;

            // Call the proper shutdown method. This is in the base type and only shuts down one of the HttpClients created (the one that's never used)
            super.shutdown(); // close the HttpClient in AmazonWebServiceClient
        }
        finally {
            // Fix a bug in Amazon's implementation where they've duplicated the HttpClients
            try {
                super.client.shutdown(); // close the HttpClient in AmazonEC2Client
            }
            catch (Throwable t) {
                // ignore failures
            }
        }
    }
}

【讨论】:

  • 非常有趣。谢谢。我将在今天晚些时候进行试验。
  • 我试过了,警告仍然存在。我不明白你为什么说“他们打开了两个 HttpClients 并且只关闭了其中一个”。所有这些类都是 AmazonWebServiceClient 的后代,其中包含 HttpClient 客户端(一个实例)并且 shutdown() 方法调用 client.shutdown(),因此在您的实现中,您在同一个对象上调用了两次相同的方法。如我错了请纠正我。在旁注中,我看到 AWS SDK 1.2.1 已经发布并使用 HttpClient 4,我必须更改一些代码才能使用它。你认为这个新版本还会存在这个错误吗?
  • 在shutdown()的JavaDoc中“关闭这个客户端对象,释放任何可能保持打开的资源。这是一个可选方法,调用者不应该调用它,但如果他们可以想要显式释放任何打开的资源。一旦客户端关闭,就不应再使用它发出任何请求。” -- 但是,它也不会被自动调用,因为如果我在那里放一个断点,它就不会被命中。我可以将所有引用保存在我的工厂中,然后循环它们,但这会阻止对它们进行垃圾收集。
  • 啊,是的,我假设您正在从代码中调用 shutdown()。在 SDK 的版本中,这是基于实际上有两个具有不同可见性的 HttpClients,super.shutdown() 关闭一个但不是通过 super.client 可见的那个......我会看看 sdk 1.2 .1,感谢您的信息:-)
【解决方案2】:

更新到 AWS Java SDK 版本 1.2.1 解决了这个问题。这个版本在我发布问题时还没有,因为它是在 2011 年 5 月 26 日发布的。

AWS SDK 1.2.* 使用 2009 年发布的 HttpClient 4,但 AWS Java SDK 在其 1.1.* 版本中仍在使用版本 3。由于我的问题已经解决,我不会再详细分析他们的代码更改。

【讨论】:

    【解决方案3】:

    我在axis2 Web服务中也遇到了类似的错误,发现它是一个bug在axis2 1.6版本中修复。

    虽然这个问题是针对 AWS 回答的,但我已经为那些正在寻找类似 axis2 错误的人提供了答案。

    【讨论】:

      猜你喜欢
      • 2017-06-09
      • 2017-11-10
      • 2011-08-19
      • 2014-09-27
      • 2017-12-26
      • 2014-10-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多