“资源泄漏:流永远不会关闭”的背景

时间:2020-04-17 07:31:55

标签: java java-stream resource-leak

给出使用流的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 /编译器给我警告:资源泄漏:'a'从未关闭

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循环时,为什么根本会发生资源泄漏?如果仅选择添加映射步骤,为什么会发生资源泄漏? (为什么在该函数的第一个版本中没有资源泄漏?)有条件地组合处理流是否“危险”?我想念什么?

1 个答案:

答案 0 :(得分:0)

我再次总结 @Nikolas 的答案:在Java中没有问题,但是“问题”(如果要这么称呼)是变量。如果将变量声明为实现AutoCloseable的类型(并且Stream确实如此),则Eclipse显然会在此处警告警告:如果找不到对{{1}的调用,则该变量未关闭}。

由于此错误与Eclipse有关,因此其他检查工具很可能不会对此失败,并且不需要“固定”通过这样的检查。

据我了解,这显示了Java的一个基本问题,即Java不会在不再需要它时就在某个随机点上释放该对象。有了资源,那将失败。因此,开发人员必须手动跟踪资源,在何处关闭资源,并手动将其关闭。 Java运行时(假设)必须实现类似C ++的close()之类的方法,这样就不必要了,如果删除了对资源的最后一个引用,则可以将其关闭。但这不像Java的“思维”。

相关问题