【问题标题】:Resource leak: 'in' is never closed资源泄漏:'in' 永远不会关闭
【发布时间】:2012-09-13 05:10:16
【问题描述】:

为什么 Eclipse 在下面的代码中给了我温暖的“资源泄漏:'in' is never closed”?

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();

【问题讨论】:

  • 致未来的读者:许多答案表明您必须关闭扫描仪才能关闭底层资源。虽然这通常是正确的,但 standard in 是一个例外。关闭它会阻止您再次阅读它,这通常是不希望的。作为一个经验法则:不要关闭你没有打开的东西。

标签: java eclipse input resources memory-leaks


【解决方案1】:

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

【讨论】:

    【解决方案2】:
    // 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.
    

    【讨论】:

      【解决方案3】:

      正如其他人所说,您需要在 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)) {
          ... 
      }
      

      【讨论】:

      • 资源泄露是什么意思,对我有什么影响?
      • @Borat - “资源泄漏”意味着某些系统资源(通常是内存)正在丢失或不必要地浪费。通常,当您在程序正常运行期间开始抛出 OutOfMemoryErrors 时,这会影响您。
      • 谢谢埃里克。我知道您可以通过在无限循环中将字符串附加到自身来导致错误。我不确定扫描仪如何导致该错误。
      • 试试资源怎么样?
      • 谢谢丹尼斯,添加。
      【解决方案4】:
      Scanner sc = new Scanner(System.in);
      
      //do stuff with sc
      
      sc.close();//write at end of code.
      

      【讨论】:

        【解决方案5】:

        如果你使用的是 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();
        }
        

        【讨论】:

        • 请注意,catch 子句不是强制性的。如果您只想确保即使在发生异常时也关闭资源,但将异常处理保留在 OP 的原始代码中(即根本没有捕获),您可以只使用 try 所示而不使用catch 子句。
        【解决方案6】:
        in.close();
        scannerObject.close(); 
        

        它将关闭Scanner并关闭警告。

        【讨论】:

          【解决方案7】:

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

          HTH, 曼弗雷德。

          【讨论】:

            【解决方案8】:

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

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

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

            Eclipse Java 编译器能够分析代码是否使用了此类 types 遵守此政策。

            ...

            编译器会将 [violations] 标记为“资源泄漏:'stream' 永远不会关闭”。

            完整解释here.

            【讨论】:

              【解决方案9】:
              private static Scanner in;
              

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

              【讨论】:

              • 您忽略了警告但造成了资源泄漏
              【解决方案10】:

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

              【讨论】:

              • 这个答案实际上帮助 OP 知道他为什么应该关闭这个东西。当然,他可以阅读文档并查看“scanner.close()”,但这个答案确实有助于他/她了解发生了什么。 + 1
              【解决方案11】:

              它告诉你需要用Scanner.close() 关闭你在System.in 上实例化的扫描程序。通常每个阅读器都应该关闭。

              请注意,如果您关闭 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: "));
                  ...
              }
              

              【讨论】:

              • 请注意,System.console() 在通过 Eclipse 运行应用程序时不可用,这在开发过程中可能会很麻烦。
              【解决方案12】:

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

              【讨论】:

                【解决方案13】:

                完成后,您应该close您的扫描仪:

                in.close();
                

                【讨论】:

                  【解决方案14】:

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

                  in.close();
                  

                  【讨论】:

                  • 这将关闭Scanner 并使警告静音,但它也会关闭System.in,这通常是不可取的。
                  • @StuartCook +1。需要注意的地方。
                  • 为什么我们需要关闭 Scanner ? “资源泄漏”是什么意思?
                  • @nogard: 你的回答真的很有帮助.. 但是当我使用 in.close();.. 再次显示无法解决.. 我有一个没有异常处理的代码.. 谢谢
                  • @StuartCook,您忘了提及为什么关闭System.in 通常是不可取的。这是因为您将无法再次读取它。 IE。例如,如果您尝试拨打(new Scanner(System.in)).nextLine(),您将收到java.util.NoSuchElementException: No line found
                  猜你喜欢
                  • 1970-01-01
                  • 2020-07-30
                  • 2012-12-20
                  • 1970-01-01
                  • 1970-01-01
                  • 2014-12-21
                  • 2014-08-19
                  • 1970-01-01
                  • 2015-03-30
                  相关资源
                  最近更新 更多