Нужно ли закрывать InputStreamReader, даже если InputStream должен оставаться открытым? - PullRequest
1 голос
/ 06 апреля 2019

InputStream передается как параметр откуда-то, где он будет дополнительно обрабатываться и затем закрываться.Поэтому я не хочу закрывать InputStream здесь.Рассмотрим следующий код:

void readInputStream(final InputStream inputStream) {
    final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
    String line;
    while ((line = bufferedReader.readLine() != null) {
        // do my thing
    }
}

Если я закрою BufferedReader и / или InputStreamReader, то базовый InputStream также будет закрыт, согласно другому сообщению Stackoverflow.

Мой вопрос: нужно ли закрывать читатели, даже если базовый InputStream закрыт где-то еще?Могу ли я получить утечку памяти, не закрывая Readers?

1 Ответ

4 голосов
/ 06 апреля 2019

Нужно ли закрывать считыватели, даже если базовый InputStream закрыт где-то еще?

Нет, они абсолютно не должны быть в этом сценарии.Но, как правило, в любом случае рекомендуется закрыть их.

Можно ли получить утечку памяти, не закрывая считыватели?

Нет, утечки памяти нет, есличто Reader сам станет недоступным, как только вы покончили с ним.И кроме того, Reader обычно не использует много памяти.

Более важный вопрос заключается в том, можно ли получить утечку resource , не закрывая Reader.Ответ ... это зависит.

  • Если вы можете гарантировать, что базовый InputStream всегда будет закрыт где-то еще в приложении, тогда , что принимаетзаботиться о возможных утечках памяти.

  • Если вы не можете гарантировать это, существует риск утечки ресурса.Базовые файловые дескрипторы уровня ОС являются ограниченным ресурсом (например) в Linux.Если JVM не закроет их, они могут закончиться, и некоторые системные вызовы начнут неожиданно завершаться с ошибкой.

Но если вы делаете , закройте Reader тогда базовый InputStream будет закрыт.

Вызов close() более одного раза на InputStream безвреден и почти ничего не стоит.

Единственный случай, когда вы не должны закрыть Reader, - это когда было бы неправильно закрывать базовый InputStream.Например, если вы закроете SocketInputStream, остальная часть приложения, возможно, не сможет восстановить сетевое соединение.Аналогично, InputStream, связанный с System.in, обычно не может быть повторно открыт.

В этом случае на самом деле можно разрешить сборку Reader, созданную в вашем методе, для сбора мусора.В отличие от InputStream, типичный класс Reader не переопределяет Object::finalize() для закрытия источника данных.


@ Pshemo поднимает важный вопрос о дизайне системы.

Если вы принимаете InputStream в качестве аргумента, то может быть неправильно заключать его в локальный Reader ... особенно BufferedReader.`BufferedReader подвержен упреждающему чтению в потоке.Если поток будет использоваться вызывающей стороной после , который возвращает ваш метод, то любые данные, которые были считаны в буфер, но не использованы этим методом, могут быть потеряны.

Лучшей идеей для вызывающего абонента было бы передать Reader.В качестве альтернативы, этот метод должен быть задокументирован как , вступающий во владение InputStreamИ в этом случае оно должно всегда close() оно.

...