如何在 Java 中检查是否有任何 IO 流打开并强制关闭它

How to check if any IO stream is open and forcefully close it in Java

提问人:Shaggy 提问时间:9/10/2023 最后编辑:Shaggy 更新时间:9/10/2023 访问量:36

问:

因此,我正在使用 Spring Boot 制作一个存档器应用程序,每当应用程序启动时,从数据库获取数据,上传到 S3,它应该会自动关闭。

所以,我在application.yml中使用了以下属性

spring:
   main:
    web-application-type: none

它的工作方式除外,例如,每当我的应用程序启动时:它使 S3 客户端,建立数据库连接,使用 Hibernate 从数据库获取数据,使用 PutObject 上传到 S3 并关闭。

原木:

2023-09-10 01:04:51.578  INFO 14992 --- [           main] c.j.m.s.ArchiverBusinessServiceImpl  : Archiver process completed with status SUCCESS
2023-09-10 01:04:51.592  INFO 14992 --- [ionShutdownHook] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2023-09-10 01:04:51.595  INFO 14992 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2023-09-10 01:04:55.606  INFO 14992 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.

Process finished with exit code 0

但最近,为了提高 S3 性能(因为我一次上传大约 1-2 百万个文件),我开始使用传输管理器。 因此,现在应用程序从数据库中获取数据,在目录中转换文件,将该目录用于传输管理器,以便在 s3 中批量上传。

问题是,一切都按预期工作,只是这次应用程序没有关闭。 它只是停在

2023-09-10 01:04:51.578  INFO 14992 --- [           main] c.j.m.s.ArchiverBusinessServiceImpl  : Archiver process completed with status SUCCESS

所以,当我做一些分析时,看起来像 PrintWriter(用于创建文件)导致这个问题,即它在操作结束时没有关闭。

但是,我正在使用 try-with-resource 关闭 printwriter,也尝试使用 close() 方法。

需要帮助来解决这个问题。

下面是代码片段:

用于创建文件

public void storeFile(KeyEntity keyEntity, List<JsonObject> jsonObjects, String archiveDate) {

        String fileName= getFileName(archiveDate,keyEntity);
        String path = ArchiveProperties.getFileUploadPath();
        Path dir= Paths.get(path);

        if(!Files.exists(dir)){
            try {
                Files.createDirectories(dir);
            } catch (IOException e) {
                log.error("Exception occurred while creating directory {}",ArchiveProperties.getFileUploadPath());
                throw new RuntimeException(e);
            }
        }
        Path file = Paths.get(path,fileName);
        try(PrintWriter printWriter = new PrintWriter(new FileWriter(file.toFile()))){
            printWriter.print(jsonObjects);
        } catch (IOException e) {
            log.error("Exception occurred while writing into directory {} for filename {}", ArchiveProperties.getFileUploadPath(), fileName);
            throw new RuntimeException(e);
        }
    }

使用传输管理器上传目录:

public Boolean bulkUpload(String path, S3Properties s3Properties,String filePrefix){

        log.info("S3ObjectStore:bulkUpload :: Initialing bulk upload for path {}",path);

        AmazonS3Client s3 = S3Configuration.getS3Client(provider,s3Properties);
        TransferManager transferManager = TransferManagerBuilder.standard().withS3Client(s3).build();
        try {

            MultipleFileUpload multipleFileUpload = transferManager.uploadDirectory(s3Properties.getBucket(),filePrefix,new File(path),false);
            showTransferProgress(multipleFileUpload);
            multipleFileUpload.waitForCompletion();

        }
        catch ( Exception e) {
            log.error("S3ObjectStore:bulkUpload :: Exception occurred while uploading directory to s3",e);
            return Boolean.FALSE;
        }finally {
            transferManager.shutdownNow();
          
        }
        return Boolean.TRUE;
    }

public static AmazonS3Client getS3Client(final IdaS3ClientKeysProvider provider, final S3Properties s3Properties){

        log.info("Creating AmazonS3Client for bulk upload ..............");
        IdaS3ClientKeysProvider idaS3ClientKeysProvider = provider;
        //Set up the connection configuration
        ClientConfiguration config = new ClientConfiguration().withRetryPolicy(ClientConfiguration.DEFAULT_RETRY_POLICY);
        //DEFAULT_RETRY_POLICY=3 times retry for failure files
        config.setProtocol(Protocol.HTTPS);
        config.setSignerOverride("S3SignerType");
        //Set up the AWS credentials
        BasicAWSCredentials credentials = new BasicAWSCredentials(idaS3ClientKeysProvider.getS3Keys().getS3AccessKey(),idaS3ClientKeysProvider.getS3Keys().getS3SecretKey());
        //Set up AWS Client
        AmazonS3Client client = new AmazonS3Client(credentials,config);
        client.setS3ClientOptions(S3ClientOptions.builder().setPathStyleAccess(true).build());
        client.setEndpoint(s3Properties.getDataplaneEndpoint());
        log.info("Inside AmazonS3Client :: access key :{}, secret key :{}",provider.getS3Keys().getS3AccessKey(),provider.getS3Keys().getS3SecretKey());
        return client;
    }

预期:应用程序应自动关闭/关闭

java spring-boot amazon-s3 io awss3transfermanager

评论

0赞 Kayaman 9/10/2023
你是如何确定没有关闭的?这也不应该阻止关闭。PrintWriter
0赞 Shaggy 9/10/2023
当我注释掉 PrintWriter 代码时,应用程序关闭了
0赞 Kayaman 9/10/2023
那么,你为什么不对应用程序进行剖析,并获得比这更好的见解。

答: 暂无答案