【问题标题】:Background of "resource leak: stream is never closed"“资源泄漏:流永远不会关闭”的背景
【发布时间】:2020-07-30 15:17:12
【问题描述】:

给定一个使用流的 Java 函数:

List<String> function(List<String> input) {
    Stream<String> a = input.parallelStream();
    Stream<String> b = a.map(c -> c.toString());
    return b.collect(Collectors.toList());
}

现在,我想控制映射是否由参数执行。 Eclipse/编译器给了我一个警告:Resource leak: 'a' is never closed

List<String> function(List<String> input, boolean doMap) {
    Stream<String> a = input.parallelStream(); // Resource leak: 'a' is never closed
    Stream<String> b = doMap ? a.map(c -> c.toString()) : a;
    return b.collect(Collectors.toList());
}

我可以使用 try-with-resources 语句解决这个问题:

List<String> function(List<String> input, boolean doMap) {
    try (Stream<String> a = input.parallelStream()) {
        Stream<String> b = doMap ? a.map(c -> c.toString()) : a;
        return b.collect(Collectors.toList());
    }
}

我的问题是:当我使用流而不是 for 循环时,为什么会出现资源泄漏?如果我只可选地添加映射步骤,为什么会出现资源泄漏? (为什么在函数的第一个版本中没有资源泄漏?)有条件地组合处理流是否“危险”?我错过了什么?

【问题讨论】:

  • 我是上述问题的提问者。 Stream 实现了导致问题的AutoCloseable。这是 Eclipse 特有的,我无法在 Intellij Idea 中重现。随意压制警告,不关闭此资源没有危险。 Java 8 的 AutoCloseableJavaDoc 证实了这一点(虽然不是 Java 7)。

标签: java java-stream resource-leak


【解决方案1】:

我再次总结 @Nikolas 的回答,换句话说:Java 没有问题,但“问题”(如果你想这么称呼它的话)是变量。如果将变量声明为实现AutoCloseable 的类型(并且Stream 实现了),Eclipse 显然会在此处报告一个警告,即它没有被关闭,如果它没有找到对close() 的调用。

由于此错误与 Eclipse 相关,因此其他检查工具可能不会因此而失败,并且不需要“修复”即可通过此类检查。

据我了解,这显示了 Java 的一个基本问题,即它不会在不再需要时立即释放变量上的对象,而是在某个随机点。有了资源,就失败了。因此,资源必须由开发人员手动跟踪,在哪里关闭它们,并手动关闭它们。 Java 运行时(假设)必须实现像 C++ 的std::auto_ptr 这样的方法,那么这将不是必需的,如果对资源的最后引用被删除,则可以关闭它。但这不像java“认为”。

【讨论】:

    猜你喜欢
    • 2012-09-13
    • 1970-01-01
    • 2012-12-20
    • 1970-01-01
    • 1970-01-01
    • 2014-12-21
    • 2014-08-19
    • 1970-01-01
    • 2014-06-11
    相关资源
    最近更新 更多