AWS SDK - AmazonS3Client无法关闭。

3
我发现创建一个AmazonS3Client会导致进程即使没有执行任何操作也一直挂起。我正在执行文件上传,但我已经将其缩减到以下代码。
当我运行以下代码(使用有效的凭据)时,它会打印“Simple is finished”,但进程直到最终maven:exec告诉我才退出:
Simple is finished
[WARNING] thread Thread[java-sdk-http-connection-reaper,5,Simple] was interrupted but is still alive after waiting at least 15000msecs
[WARNING] thread Thread[java-sdk-http-connection-reaper,5,Simple] will linger despite being asked to die via interruption
[WARNING] NOTE: 1 thread(s) did not finish despite being asked to  via interruption. This is not a problem with exec:java, it is a problem with the running code. Although not serious, it should be remedied.
[WARNING] Couldn't destroy threadgroup org.codehaus.mojo.exec.ExecJavaMojo$IsolatedThreadGroup[name=Simple,maxpri=10]
java.lang.IllegalThreadStateException

代码如下:
    import com.amazonaws.auth.AWSCredentials;
    import com.amazonaws.auth.BasicAWSCredentials;
    import com.amazonaws.services.s3.AmazonS3;
    import com.amazonaws.services.s3.AmazonS3Client;

    public class Simple {

        private static String accessKey = "XXX";
        private static String secretKey = "ZZZ";

        public static void main(String[] args) {

            AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);
            AmazonS3 s3client = new AmazonS3Client(credentials);
            System.out.println("Simple is finished");        
        }

    }

这是正常的工作方式吗?有没有一种方法可以终止它?
编辑:添加版本信息:
<dependency>
    <groupId>com.amazonaws</groupId>
    <artifactId>aws-java-sdk</artifactId>
    <version>1.9.33</version>
</dependency>
3个回答

6

两者似乎都可以:

((AmazonS3Client) s3client).shutdown();

或者

try {
    com.amazonaws.http.IdleConnectionReaper.shutdown();
} catch (Throwable t) {
    // etc
}

虽然我不确定它们有多正确。

你对这个问题和解决方案有更深入的了解吗?具体来说,为什么我们必须自己调用shutdown?为什么在关闭S3Object时不执行它?你是否在ServletContextListener()的contextDestroyed()方法中调用了shutdown()? - theyuv
@woddle 如果我只想将连接释放回池中怎么办?似乎 #shutdown() 不是在这种情况下正确的方法。有没有一些通用的方式可以做到这一点? - Norbert
@Norbert,很抱歉我无法发表评论。 - woddle

2

我希望在推荐这个解决方案时能够提供更多的背景信息,因为我无法发表评论:

((AmazonS3Client) s3client).shutdown();

根据aws开发者指南,连接池资源直到客户端被垃圾回收才会被清理。调用shutdown强制客户端释放其资源,这就是为什么这个解决方案有效的原因。
下面是AmazonWebServiceClient.java(AmazonS3Client的父类)中的shutdown方法:
/**
 * Shuts down this client object, releasing any resources that might be held
 * open. This is an optional method, and callers are not expected to call
 * it, but can if they want to explicitly release any open resources. Once a
 * client has been shutdown, it should not be used to make any more
 * requests.
 */
public void shutdown() {
    client.shutdown();
}

1
上述解决方案有效,这里提供两个其他的解决方法:
  • 在AmazonS3超出范围后手动调用System.gc()
  • 或者,在运行maven时添加标志exec.cleanupDaemonThreads=false
我遇到了同样的问题。 AmazonS3Client实际上会在垃圾回收时得到清理;但是,根据您的jvm,可能永远不会发生。 在我的情况下,即使使用-Dexec.daemonThreadJoinTimeout=-1运行,这会使maven无限期地等待线程关闭,它也从未关闭。
aws-java-sdk-s3版本为1.10.24

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