AmazonS3Builder 生成有效的 AmazonS3 对象,但最终返回 null

AmazonS3Builder produces valid AmazonS3 object but a null is ultimately returned

我正在使用 AWS Java SDK v1,并且正在尝试使用构建器创建 AmazonS3 实例。我遵循 AWS 文档 here 中的指南并使用 BasicAWSCredentials 对象传递显式凭证。当构建器构建时,我将一个空客户端返回到 s3Client,这是我存储实例的地方,我不确定为什么。 try-catch 块不会抛出或捕获任何错误。以下是我建立连接的方式:

    BasicAWSCredentials awsCreds = null;
    try {
        awsCreds = new BasicAWSCredentials(settings.getAccessKey(), settings.getSecretKey());
    } catch (Exception e) {
        e.printStackTrace();
        throw new IOException(e.getMessage());
    }

    try {
        AmazonS3 s3Client = AmazonS3Client.builder()
                .withCredentials(new AWSStaticCredentialsProvider(awsCreds))
                .withRegion(Regions.US_EAST_1)
                .build();
    } catch (Exception e) {
        e.printStackTrace();
    }
    System.out.println(s3Client);

我已经使用 Eclipse 调试器逐步完成它,看起来 build() 调用实际上是 returning 一个有效的 AmazonS3Client 实例,但是在此引用之前 returned回到 s3Client 变量,有一个调用 checkPackageAccess() 的步骤,这个 return 值是由于某种原因被 return 返回的值。在进一步检查中,我发现 checkPackageAccess() 是 JVM 调用的 java.lang.ClassLoader 中的一个方法,并且它具有 void return 类型。在我的应用程序中,似乎没有设置默认的 SecurityManager,因此在 ClassLoader 的 checkPackageAccess() 方法中没有调用其他函数。

我对这种行为有点困惑。我的 JRE 是 1.8。据我了解,在查找class定义时总是调用ClassLoader,但是为什么在class已经实例化之后调用它,为什么原来的return build() 函数的值没有返回到调用者上下文?在这种情况下,调试器显示存在一个有效的 AmazonS3Client 对象,并且甚至在调用 checkPackageAccess 之前 return 通过调用 build() 编辑。

我之前在同一个项目中用几乎相同的代码创建了一个 AmazonRedshift 实例,并且运行顺利,所以我非常肯定问题出在 AmazonS3 class 或构建器上,但我不确定在哪里,也没有看到任何错误或奇怪的印刷品。

用于与 Amazon Redshift 建立类似连接的代码:

        BasicAWSCredentials awsCreds = null;
    try {
        awsCreds = new BasicAWSCredentials(ACCESS_KEY, SECRET_KEY);
    } catch (Exception e) {
        e.printStackTrace();
        throw new IOException(e.getMessage());
    }
    try {
        client = AmazonRedshiftClientBuilder.standard()
                                .withCredentials(new AWSStaticCredentialsProvider(awsCreds))
                                .withRegion(Regions.US_EAST_1)
                                .build();
    } catch (Exception e) {
        e.printStackTrace();
    }
    System.out.println(client);

有没有人调试过这种问题?我该怎么做才能解决这个问题并取回有效实例?

您是否愿意从自己的 class 而不是 S3Client 方法 builder() 构建您的构建器?以下代码与您的 Redshift 案例相似,对我来说工作正常。

    static final String BUCKET_NAME = "hello-world";

    /** Creates bucket
    @param args Command line arguments*/
    public static void main(final String[] args) {

            AmazonS3 s3 = AmazonS3ClientBuilder.standard().build();

            CreateBucketRequest request = new
                    CreateBucketRequest(BUCKET_NAME);

            Bucket bucket = s3.createBucket(request);

    System.out.println("S3 Hello World completed.");

无论如何,我的编译器找不到静态 builder() 方法,尽管它确实在 API.

问题最终变得更加根本。我觉得写这个几乎是尴尬的。我不得不重新审视我的代码才能找到它,但我在 try 块中重新声明了 s3Client。

private AmazonS3 s3Client = null;

...

BasicAWSCredentials awsCreds = null;
try {
    awsCreds = new BasicAWSCredentials(settings.getAccessKey(), settings.getSecretKey());
} catch (Exception e) {
    e.printStackTrace();
    throw new IOException(e.getMessage());
}

try {
    AmazonS3 s3Client = AmazonS3Client.builder()
            .withCredentials(new AWSStaticCredentialsProvider(awsCreds))
            .withRegion(Regions.US_EAST_1)
            .build();
} catch (Exception e) {
    e.printStackTrace();
}
System.out.println(s3Client);

当它到达实际使用 AmazonS3 对象的代码时,持有对它的引用的局部变量已经超出了范围。真不敢相信我没听清楚。