"resource leak: stream is never closed"背景



给定一个使用流的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());
}

我可以使用资源尝试语句来解决此问题:

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 循环时会出现资源泄漏?如果我只选择性地添加映射步骤,为什么会出现资源泄漏?(为什么函数的第一个版本中没有资源泄漏?有条件地组合处理流是否"危险"?我错过了什么?

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

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

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

相关内容

  • 没有找到相关文章

最新更新