资源泄漏:'in'永远不会关闭

use*_*995 77 java eclipse resources memory-leaks input

为什么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();
Run Code Online (Sandbox Code Playgroud)

nog*_*ard 59

因为您没有关闭扫描仪

in.close();
Run Code Online (Sandbox Code Playgroud)

  • 这将关闭`Scanner`并使警告静音,但它也会关闭`System.in`,这通常是不可取的. (36认同)
  • @StuartCook,你忘了提及 **为什么** 关闭 `System.in` 通常是不可取的。这是因为您将无法再次阅读它。IE。例如,如果您尝试调用“(new Scanner(System.in)).nextLine()”,您将得到“java.util.NoSuchElementException:找不到行”。 (6认同)
  • 为什么我们需要关闭扫描仪?"资源泄漏"是什么意思? (4认同)
  • @nogard:你的回答真的很有帮助..但是当我使用in.close();..它再次显示无法解析..我有一个没有异常处理的代码..谢谢 (2认同)

Eri*_*uer 46

正如其他人所说,你需要在IO类上调用'close'.我将补充一点,这是一个使用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();
    }
}
Run Code Online (Sandbox Code Playgroud)

这可确保您的扫描仪始终处于关闭状态,从而确保正确的资源清理.

同样,在Java 7或更高版本中,您可以使用"try-with-resources"语法:

try (Scanner in = new Scanner(System.in)) {
    ... 
}
Run Code Online (Sandbox Code Playgroud)

  • @Borat - "资源泄漏"意味着某些系统资源(通常是内存)不必要地丢失或浪费.通常,当您开始在程序的正常操作期间抛出OutOfMemoryErrors时,这会影响您. (5认同)
  • 尝试资源怎么样? (3认同)
  • 资源泄漏是什么意思,它将如何影响我? (2认同)

Wil*_*ill 10

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

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

实现接口java.io.Closeable(自JDK 1.5以来)和java.lang.AutoCloseable(自JDK 1.7以来)的类被视为表示外部资源,当不再需要它们时,应使用close()方法关闭它们.

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

...

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

完整的解释在这里.


Ale*_*lex 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: "));
    ...
}
Run Code Online (Sandbox Code Playgroud)

  • 请注意,通过Eclipse运行应用程序时,`System.console()`不可用,这在开发过程中可能很麻烦. (3认同)

agy*_*eya 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();
}
Run Code Online (Sandbox Code Playgroud)


Aas*_*shi 6

// An InputStream which is typically connected to keyboard input of console programs

Scanner in= new Scanner(System.in);
Run Code Online (Sandbox Code Playgroud)

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

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

//Write piece of code 
Run Code Online (Sandbox Code Playgroud)

要消除内存泄漏 -

in.close();//write at end of code.
Run Code Online (Sandbox Code Playgroud)


小智 5

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

HTH,曼弗雷德。


Cha*_*tin 5

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