Как реализовать Stream <E>без предупреждения об утечке ресурсов в Java - PullRequest
0 голосов
/ 27 декабря 2018

Я хочу реализовать интерфейс Stream<E> (я признаю, что он неоправданно большой) и добавить метод конструктора foo().

public MyStream<E> implements Stream<E>, ExtendedStream<E> {

    private final Stream<E> delegate;

    public MyStream(final Stream<E> stream) {
        this.delegate = stream;
    }

    // a sample Stream<E> method implementation
    @Override
    public <R> MyStream<R> map(Function<? super E, ? extends R> mapper) {
        return new MyStream<>(this.delegate.map(mapper));
    }
    // the rest in the same way (skipped)

    // a method from ExtendedStream<E>
    @Override
    public MyStream<E> foo() {
        return new MyStream(this.delegate.......);
    }  
}

Пока все хорошо.

long count = new MyStream(list.stream())
    .map(i -> i * 10)
    .foo()
    .filter(i -> i > 100)
    .count();

У меня проблемы с поведением Closeable Stream.Документация Stream говорит о закрытии (форматировании шахты):

Потоки имеют метод BaseStream.close() и реализуют AutoCloseable, но почти все экземпляры потоков фактически не имеютдолжны быть закрыты после использования.Как правило, только потоки, источником которых является канал ввода-вывода (например, те, которые возвращаются Files.lines(Path, Charset)), требуют закрытия.

Единственными методами, которые закрывают Stream, являются flatMap или close.

Создание объекта в Eclipse Oxygen подчеркнуто предупреждением:

Утечка ресурсов: '<unassigned Closeable value>' никогда не закрывается

Это не воспроизводится с IntelliJIdea 2018.1.5 . Смежными вопросами, которые я просматривал, являются здесь и здесь . Я понимаю Closeable проблемы с File или Dictionary, однако, я застрял с потоками.

Мне не нравится статический метод MyStream.of(...), вызывающий обходной путь частного конструктора.

Ответы [ 2 ]

0 голосов
/ 30 декабря 2018

В рамках работы над JSR 335 библиотеки JRE развивались благодаря введению java.util.Stream и одновременному использованию новой концепции в таких местах, как java.nio.В течение этого времени группа экспертов по Eclipse консультировалась с группой экспертов JSR 335, чтобы обсудить следующий конфликт :

  • Инструменты типа ecj хотят сигнализировать, когда программисты забывают закрытьресурс, устойчивый к GC (GCR), такой как, например, FileInputStream.

  • . Команда библиотеки планировала сделать java.util.Stream подтипом AutoCloseable, чтобы разрешить использование в try-with-resource, мотивированный тем фактом, что j.u.Stream может потенциально быть поддержан ресурсом GCR.Тем не менее, по умолчанию предполагается, что экземпляры j.u.Stream do не требуют close() вызова.

  • Тем не менее, некоторые методы в java.nio возвращают j.u.Stream требует, чтобы было close() d.

EG и Eclipse согласились, что не может быть найдено простого решения , такого, что просто взглянув на тип закрываемого любой инструмент может точно распознать , необходимо ли закрытие или нет.Это связано с тонкостью различных ресурсов , обертывающих других ресурсов на нескольких уровнях.В частности, тип j.u.Stream не указывает, поддерживаются ли экземпляры ресурсами GCR или нет.

Для чистого решения было также упомянуто, что система аннотаций типов (использующая JSR 308) будетпонадобиться для обогащения системы типов информацией, необходимой для точного статического анализа.Насколько мне известно, такой подход не был реализован до сегодняшнего дня.

В качестве компромисса разработчикам инструментов, таким как Eclipse, было рекомендовано кодировать эвристику по следующим направлениям:

  • Обычно все экземпляры типа AutoCloseable должны быть закрыты.

  • Следующий известный набор типов должен был быть исключен из анализа, поскольку эти обычно не требуют закрытия: java.util.Stream и {Int,Long,Double}Stream.

  • Как исключение из исключения, некоторые статические методы, возвращающие поток, в java.nio известны как require закрытие.

Обсуждение в основном происходило между следующими двумя постами в списке рассылки lambda-libs-spec-наблюдателей:

Так многодля истории.

Дискуссия в 2013 году не получилане для пользовательских реализаций из j.u.Stream.Eclipse не предполагает никаких конкретных знаний об этих реализациях.Было бы лучше, если бы инструмент не решал смещение в сторону необходимости / не необходимости закрытия (), но если бы у разработчика (здесь MyStream) были бы средства, чтобы указать, требуют ли экземпляры этого класса закрытия или нет.Однако у современных разработчиков нет средств выразить это.

Из-за отсутствия полной и точной опции мы могли бы обсудить расширение набора эвристик, чтобы не только известный набор типов в j.u.Stream семейство, но также все его подтипы исключены из анализа и считаются GC-дружественными.Очевидно, что такой подход увеличил бы риск ложных негативов (ошибок, пропущенных анализом).

Маркировка предупреждений как "потенциальных утечек", как предполагает ответ Хоулгера, может привести к путанице, потому что в анализе потока слово«Потенциал» обычно должен указывать на поведение, которое происходит в некоторых, но не во всех потоках, проходящих через программу.

На сегодняшний день доступны следующие параметры:

  • Использование @SuppressWarnings("resource") везде, где используется MyStream (предпочтительно)

  • Понижение серьезности этой конкретной проблемы (если использование MyStream слишком широко распространено для использования первой опции).

0 голосов
/ 28 декабря 2018

В Java 7 описание AutoCloseable равно

"... должно быть закрыто ..."

, тогда как в Java 8 описание было семантически изменено на

" ... что можетудерживать ресурсы (например, дескрипторы файлов или сокетов) ... "

В Eclipse предупреждение об утечке ресурсов отображается независимо от версии Java для всех экземпляров Closeable и AutoCloseable, которыене закрываются (что имеет место в вашем примере).См. Справка по Eclipse :

Классы, реализующие интерфейс java.io.Closeable (начиная с JDK 1.5) и java.lang.AutoCloseable (начиная с JDK 1.7) считаются представляющими внешние ресурсы,который должен быть закрыт с использованием метода close(), когда они больше не нужны.

В соответствии с измененным описанием Javadoc, я ожидал бы в Java 8 или выше для не закрытого AutoCloseable только предупреждение о потенциальной утечке 1043 * вместо предупреждения утечка ресурсов .Стефан Херрманн, разработчик Eclipse JDT, объясняет в своем ответе, почему он не считает это хорошей идеей .

В качестве обходного пути для Java 8 или выше добавьте @SuppressWarnings("resource") кте места, где AutoCloseable не нужно закрывать.

...