Как исправить ошибку потока: может не получиться закрыть ошибку потока

#java #stream #findbugs #software-quality

Вопрос:

Я пишу метод, но вижу эту ошибку: возможно, не удастся закрыть поток. Согласно некоторым решениям в разных сообщениях, я добавил «попробуйте и поймайте» в блоке «Наконец». Я также добавил IOUtils.closeQuietly(полный объект, (Журнал) РЕГИСТРАТОР). Но это все равно не работает. Кто-нибудь может помочь взглянуть? Спасибо!

         S3Object fullObject = null;
        StringBuffer buffer = new StringBuffer();

        try {
            S3Object s3Response = s3Client.getObject(s3BucketName, s3Key);
            BufferedReader reader = new BufferedReader(new InputStreamReader(s3Response.getObjectContent()));
            String line;
            while ((line = reader.readLine()) != null) {
                buffer.append(line);
            }
        } finally {
                if (fullObject != null) {
                    try {
                        fullObject.close();
                    } catch (IOException ex) {
                        throw new RuntimeException(ex);
                    }
                    IOUtils.closeQuietly(fullObject, (Log) LOGGER);
                }
        }
        return buffer.toString();
    }

 

Комментарии:

1. Вы пробовали поставить IOUtils.closeQuietly(fullObject, (Log) LOGGER); внутри finally блок для внутреннего try-catch ?

2. Кроме того, в текущем коде fullObject всегда null есть ?

Ответ №1:

InputStreamReader инвентарь AutoCloseable . Это означает, что предполагаемое использование try-with-resources :

 try (InputStreamReader reader = new InputStreamReader(s3Response.getObjectContent()) {
    ...
}
 

Это всегда должно закрывать поток независимо от того, как блок завершается (т. Е. через обычное завершение catch или finally предложения).

То же самое верно S3Object и для BufferedReader и. Все они могут быть объявлены как ресурсы в одном try блоке.

Видишь https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html для получения более подробной информации.

Ответ №2:

Вы должны использовать Java 7 попробуйте с ресурсами. Он позаботится о закрытии ресурсов, которые вы объявите в списке. Любые исключения, которые могут возникнуть в процессе закрытия, будут рассмотрены надлежащим образом. (Им либо разрешается распространяться, либо они «подавляются», если исключение уже распространялось.)

Ваш код, использующий try с ресурсами, будет выглядеть следующим образом. Это вдвое меньше первоначальной версии, и в ней не будет никаких утечек ресурсов. Вы «выигрываете» в обоих направлениях.

 try (S3Object s3Response = s3Client.getObject(s3BucketName, s3Key);
     BufferedReader reader = new BufferedReader(
             new InputStreamReader(s3Response.getObjectContent()));
    ) 
{
    StringBuffer buffer = new StringBuffer();
    String line;
    while ((line = reader.readLine()) != null) {
        buffer.append(line);
    }
    return buffer.toString();
}
 

Обратите внимание, что я избавился от fullObject того, что ваш код не использовал.

На самом деле в приведенном выше описании есть два управляемых ресурса: the s3Response и the reader . Возможно, нет особой необходимости закрывать оба, но (ИМО) закрывать их в любом случае правильно … с точки зрения читабельности, если ничего другого.

(Также может быть возможно сделать «чтение содержимого в виде строки» более простым и/или более эффективным, но это выходит за рамки данного вопроса.)