100

为什么 Eclipse 在下面的代码中给我温暖的“资源泄漏:'in' 永远不会关闭”?

public void readShapeData() {
        Scanner in = new Scanner(System.in);
        System.out.println("Enter the width of the Rectangle: ");
        width = in.nextDouble();
        System.out.println("Enter the height of the Rectangle: ");
        height = in.nextDouble();
4

14 回答 14

85

因为你没有关闭你的扫描仪

in.close();
于 2012-09-20T19:14:13.163 回答
67

正如其他人所说,您需要在 IO 类上调用“关闭”。我要补充一点,这是使用 try - finally 块而没有捕获的好地方,如下所示:

public void readShapeData() throws IOException {
    Scanner in = new Scanner(System.in);
    try {
        System.out.println("Enter the width of the Rectangle: ");
        width = in.nextDouble();
        System.out.println("Enter the height of the Rectangle: ");
        height = in.nextDouble();
    } finally {
        in.close();
    }
}

这可确保您的 Scanner 始终处于关闭状态,从而保证适当的资源清理。

等效地,在 Java 7 或更高版本中,您可以使用“try-with-resources”语法:

try (Scanner in = new Scanner(System.in)) {
    ... 
}
于 2012-09-20T20:06:56.650 回答
12

您需要in.close()在一个finally块中调用 , 以确保它发生。

从 Eclipse 文档中,这就是它标记这个特定问题的原因(强调我的):

实现接口java.io.Closeable(JDK 1.5 起)和java.lang.AutoCloseable(JDK 1.7 起)接口的类被认为代表外部资源,当不再需要它们时,应该使用方法 close() 将其关闭。

Eclipse Java 编译器能够分析使用此类类型的代码是否符合此策略。

...

编译器将使用“资源泄漏:'流'永远不会关闭”来标记 [违规]。

完整的解释在这里

于 2013-08-30T18:21:24.703 回答
8
// An InputStream which is typically connected to keyboard input of console programs

Scanner in= new Scanner(System.in);

上面的行将调用带有参数 System.in 的 Scanner 类的构造函数,并将返回对新构造对象的引用。

它连接到连接到键盘的输入流,因此现在在运行时您可以使用用户输入来执行所需的操作。

//Write piece of code 

要消除内存泄漏 -

in.close();//write at end of code.
于 2017-02-03T12:05:15.757 回答
7

它告诉您需要关闭您实例化的扫描System.inScanner.close()。通常每个读者都应该关闭。

请注意,如果您关闭System.in,您将无法再次读取它。你也可以看看Console课堂。

public void readShapeData() {
    Console console = System.console();
    double width = Double.parseDouble(console.readLine("Enter the width of the Rectangle: "));
    double height = Double.parseDouble(console.readLine("Enter the height of the Rectangle: "));
    ...
}
于 2012-09-20T19:30:43.313 回答
6

如果您使用的是 JDK7 或 8,您可以对资源使用 try-catch。这将自动关闭扫描仪。

try ( Scanner scanner = new Scanner(System.in); )
  {
    System.out.println("Enter the width of the Rectangle: ");
    width = scanner.nextDouble();
    System.out.println("Enter the height of the Rectangle: ");
    height = scanner.nextDouble();
  }
catch(Exception ex)
{
    //exception handling...do something (e.g., print the error message)
    ex.printStackTrace();
}
于 2015-06-17T07:16:35.483 回答
5

添加private static Scanner in;并不能真正解决问题,它只会清除警告。使扫描仪静态意味着它永远保持打开状态(或者直到类被卸载,这几乎是“永远”)。编译器不再给您任何警告,因为您告诉他“永远保持打开状态”。但这并不是您真正想要的,因为您应该在不再需要资源时立即关闭它们。

HTH,曼弗雷德。

于 2014-10-01T09:56:59.280 回答
4

完成后,您应该关闭扫描仪:

in.close();
于 2012-09-20T19:15:07.130 回答
4

好吧,说真的,至少在很多情况下,这实际上是一个错误。它也出现在 VS Code 中,它是 linter 注意到您已经到达封闭范围的末尾而没有关闭扫描仪对象,但没有认识到关闭所有打开的文件描述符是进程终止的一部分。没有资源泄漏,因为资源在终止时都被清理了,进程消失了,没有地方可以保留资源。

于 2020-09-25T15:43:02.250 回答
2

通常,处理 I/O 的类的实例应该在你完成它们之后关闭。因此,您可以在代码末尾添加in.close().

于 2012-09-20T19:15:11.243 回答
1
private static Scanner in;

我通过将其声明为私有静态 Scanner 类变量来修复它。不知道为什么要修复它,但这是 eclipse 建议我做的。

于 2013-06-04T19:29:13.207 回答
1

扫描仪应该关闭。关闭 Readers、Streams 和此类对象以释放资源和避免内存泄漏是一种很好的做法;并在 finally 块中这样做以确保即使在处理这些对象时发生异常,它们也已关闭。

于 2012-09-20T19:59:58.590 回答
0
Scanner sc = new Scanner(System.in);

//do stuff with sc

sc.close();//write at end of code.
于 2016-10-11T07:15:02.927 回答
-1
in.close();
scannerObject.close(); 

它将关闭Scanner并关闭警告。

于 2016-09-16T06:24:46.533 回答