Java 启动了名为MultiThreadedHttpConnectionManager cleanup的线程,但未能停止该线程

Java 启动了名为MultiThreadedHttpConnectionManager cleanup的线程,但未能停止该线程,java,tomcat,amazon-web-services,Java,Tomcat,Amazon Web Services,我正在使用AmazonWebServicesAWSJavaSDK编写一个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 clea

我正在使用AmazonWebServicesAWSJavaSDK编写一个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.

这是AWS SDK中的一个错误,他们打开了两个HttpClient,只关闭了其中一个。 我的问题稍有不同,因为我想启动和停止不同地区和帐户的客户端,而无需重新启动webapp

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

公共类MyAmazonEC2Client扩展了AmazonEC2AsyncClient{
私有布尔shutdownCall=false;
公共MyAmazonEC2Client(最终AWSCredentials AWSCredentials){
超级(awsCredentials);
}
公共MyAmazonEC2Client(最终AWSCredentials AWSCredentials,最终客户端配置ClientConfiguration){
这(awsCredentials、clientConfiguration、Executors.newCachedThreadPool());
}
公共MyAmazonEC2Client(
最终AWSCredentials AWSCredentials,
最终客户端配置客户端配置,
最终执行人(服务执行人){
超级(awsCredentials、客户端配置、执行器);
}
/**
*关闭此客户端对象,释放所有可能保持打开状态的资源。
*/ @凌驾 公共同步无效关机(){ 试一试{ ShutdownCall=true; //调用正确的关闭方法。这是在基类型中,只关闭创建的一个HttpClient(从未使用过的) super.shutdown();//关闭AmazonWebServiceClient中的HttpClient } 最后{ //修复Amazon实现中复制HttpClient的错误 试一试{ super.client.shutdown();//关闭AmazonEC2Client中的HttpClient } 捕获(可丢弃的t){ //忽略失败 } } } }
更新到AWS Java SDK 1.2.1版解决了问题。这个版本在我发布这个问题时还不可用,因为它是在2011年5月26日发布的


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

我在axis2 web服务中也遇到了类似的错误,并发现它是axis2 1.6版本中修复的axis中的错误


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

您100%确定调用了contextDestroyed()吗?在contextDestroyed方法中放入try-catch。好的,我正在为异常添加try-catch,并打印堆栈跟踪。但是,如果引发异常,则不会打印字符串“contextdestromed()end”。如果捕获到任何内容,我将进行更新…更新是:我添加了try/catch,继续开发其他东西,经历了许多重新部署,我从未看到在该方法中抛出异常;为我做的工作。线程正在正确关闭..非常有趣。谢谢今天晚些时候我会用它做实验。我试过了,但警告仍然存在。我不明白你为什么说“他们打开了两个httpclient,只关闭了其中一个”。所有这些类都是AmazonWebServiceClient的后代,AmazonWebServiceClient包含HttpClient客户端(一个实例),shutdown()方法调用client.shutdown(),因此在实现中,可以对同一对象调用同一方法两次。如果我错了,请纠正我。在旁注中,我看到AWS SDK 1.2.1已经发布并使用了HttpClient 4,我必须修改一些代码才能使用它。你认为这个新版本的bug还会存在吗?在shutdown()的JavaDoc中关闭此客户端对象,释放所有可能保持打开状态的资源。这是一个可选方法,调用方不需要调用它,但如果他们想显式释放任何开放资源,可以调用它。客户机关闭后,不应再使用它发出任何请求。“--然而,它也不会被自动调用,因为如果我在那里放置断点,它不会被命中。我可以保存工厂中的所有引用,然后对它们进行循环,但这会阻止对它们进行垃圾收集。在SDK版本中,这是基于实际上有两个具有不同可见性的HttpClient,super.shutdown()关闭一个,但不关闭通过super.client可见的一个。。。我将查看sdk 1.2.1,感谢您提供的信息:-)
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
            }
        }
    }
}