java - 如何在 Java 中实现没有资源泄漏警告的 Stream<E>

标签 java eclipse memory-leaks java-8 java-stream

我希望实现 Stream<E>接口(interface)(我承认,它是不必要的大)并添加一个构建器方法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 的文档说关于关闭(格式化我的):

Streams have a BaseStream.close() method and implement AutoCloseable, but nearly all stream instances do not actually need to be closed after use. Generally, only streams whose source is an IO channel (such as those returned by Files.lines(Path, Charset)) will require closing.



关闭 Stream 的唯一方法是 flatMapclose .

中对象的实例化 eclipse 氧气 带有警告下划线:

Resource leak: '<unassigned Closeable value>' is never closed



这无法通过 重现。 IntelliJidea 2018.1.5 .我浏览的相关问题是herehere .我了解 Closeable File 的问题或 Dictionary ,但是,我坚持使用 Streams。

我不喜欢静态方法MyStream.of(...)调用私有(private)构造函数解决方法。

最佳答案

作为 JSR 335 工作的一部分,JRE 库通过引入 java.util.Stream 演变而来同时在 java.nio 等地方利用新概念.在此期间,JSR 335 专家组咨询了 Eclipse 团队,讨论以下 冲突 :

  • 当程序员忘记关闭抗 GC(GCR)资源(例如 FileInputStream)时,像 ecj 这样的工具会发出信号。 .
  • 图书馆团队计划制作java.util.Stream AutoCloseable 的子类型启用在 try-with-resource 中的使用,其动机是 j.u.Stream可能由 GCR 资源支持。尽管如此,默认假设应该是 j.u.Stream 的实例。不需要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 .
  • 作为异常(exception)的一个异常(exception),java.nio 中的某些返回流的静态方法已知需要关闭。

  • 讨论基本上发生在 lambda-libs-spec-observers 邮件列表上的以下两个帖子之间:
  • Brian's problem statement & intermediate proposal
  • My summary of a private discussion .

  • 历史就是这么多。

    2013年的讨论没占到自定义实现 j.u.Stream . Eclipse 假定没有关于这些实现的特定知识。更好的是,如果不是该工具将决定是否需要关闭(),但如果实现者(此处为 MyStream)将有办法指示此类的实例是否需要关闭。然而,迄今为止的实现者无法表达这一点。

    由于缺乏完整和精确的选项,我们可以讨论扩展启发式方法集,这样不仅 j.u.Stream 中的已知类型集家族,而且它的所有亚型都被排除在分析之外,并被认为是 GC 友好的。显然,这种方法会增加误报(分析遗漏的错误)的风险。

    正如howlger 的回答所建议的那样,将警告标记为“潜在泄漏”会令人困惑,因为在流分析中,“潜在”一词通常应该表示在某些(但不是全部)流经程序时发生的行为。

    截至今天的可用选项是:
  • 使用 @SuppressWarnings("resource")在哪里MyStream使用(首选)
  • 降低这个特定问题的严重性(如果 MyStream 的使用范围太广,无法使用第一个选项)。
  • 关于java - 如何在 Java 中实现没有资源泄漏警告的 Stream<E>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53949538/

    相关文章:

    java - 有哪些 JSR 168 兼容的 Java Web 框架?

    Java AES/GCM 解密失败

    java - Eclipse Java Web 调试

    java - ThreadLocal 和内存泄漏

    c++ - 返回 const 引用或引用的方法会导致内存泄漏吗?

    java - Java ArrayList 可以为空并且 indexOf 返回索引 0 吗?

    java - 不使用 String.split() 分割字符串 - 并返回分隔符

    java - "Updating status for Apache Tomcat v7.0 at localhost..."。 java.lang.IndexOutOfBoundsException

    java - 在 Eclipse 下运行 JMH 基准测试

    JavaScript 可能存在内存泄漏