【问题标题】:Is this a memory leak or a false positive?这是内存泄漏还是误报?
【发布时间】:2012-07-12 21:09:36
【问题描述】:

这是我的代码:

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.Scanner;

public class temp {
    public static void main(String[] args) throws FileNotFoundException {
        BufferedReader a = new BufferedReader(new FileReader("a"));
        Scanner scanner = new Scanner(a).useDelimiter(",");
        scanner.close();
    }
}

我在new Scanner(a) 收到一条警告,上面写着(我正在使用 jdk1.7.0_05 进行编译。):

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

我做错了什么,还是这只是一个错误的警告?

【问题讨论】:

    标签: java eclipse memory-leaks warnings


    【解决方案1】:

    如果你这样拆分代码,警告会消失吗?

      Scanner scanner = new Scanner(a);
      scanner.useDelimiter(",");
      scanner.close();
    

    【讨论】:

    • 是的,当我这样拆分代码时,警告确实消失了。那么我的原始代码是内存泄漏吗?
    • 不,这不是泄漏,这是编译器无法正确检测到的。
    • 这是一个泄漏,如果 useDelimiter 的实现返回的不是“this”(它在当前实现中没有)。
    • @Bananeweizen,如果useDelimiter 的实现返回this 以外的东西,那么即使这个解决方案也会泄漏。 useDelimiter 的返回值永远不会关闭。够糟糕的,如果你不知道函数返回什么,没有双重关闭或类似的坏事,就没有办法防止这种泄漏。
    • 其实useDelimiter的名字和界面都不好。如果它被称为setDelimiter 并且返回类型为void 就像其他类似的方法一样,那根本不是问题。
    【解决方案2】:

    是的,您的代码有潜在的(但不是真正的)内存泄漏。您将useDelimiter(a) 的返回值分配给局部变量scanner,但构造函数结果被丢弃。这就是您收到警告的原因。

    实际上,useDelimiter(a) 的返回值与构造函数调用返回的对象完全相同,因此您的代码可以很好地关闭资源。但这是编译器/代码分析工具无法检测到的,因为它必须知道 useDelimiters 的实现。

    一个非常好的代码分析工具应该会向您显示一个附加警告,因为您正在关闭一个尚未在此方法中打开的资源(useDelimiter 的返回值)。如果您将这 2 条消息放在一起,您可能会更清楚这些症状。

    【讨论】:

      【解决方案3】:

      你试过了吗:

      Scanner scanner = new Scanner(new BufferedReader(new FileReader("a"))).useDelimiter(",");
      

      如果不起作用,您必须添加a.close();

      【讨论】:

      • 当我把它全部放在一行时,我仍然收到警告。
      • 尝试删除main()中的throws FileNotFoundException并在BufferedReader周围添加一个try/cath块,buff.close()finally中。
      【解决方案4】:

      是什么给了你这个警告?大概它会发出警告,因为分配/关闭不是在 try/finally 块中完成的,这通常是一个坏主意(在这种特定情况下不是问题,因为唯一可以引发错误的是新的 FileReader 并且如果它throws 实际上没有分配任何资源 - 但这可以通过单个方法调用来改变..)

      关闭扫描器会关闭底层流(确切地说是任何实现自身的东西Closeable(是的BufferedReader 确实如此)所以除此之外代码都很好。

      【讨论】:

      • 我尝试将它放在 try 块中,并在 finally 块中关闭,但我仍然收到警告。
      • @din 在这种情况下,无论您使用的是哪个静态分析器,都是错误的。
      • 在这种情况下,try 块将无济于事,因为如果分配扫描仪的语句中有异常,则无需关闭任何内容。
      • @Francis 是的,我们知道,但在某些情况下,工具(或程序员)无法确定是否会发生任何运行时异常,因此在所有情况下发出警告似乎都是一个简单的解决方案避免误报。
      猜你喜欢
      • 2011-05-03
      • 2014-06-30
      • 1970-01-01
      • 1970-01-01
      • 2011-02-20
      • 2013-08-12
      • 1970-01-01
      相关资源
      最近更新 更多