【问题标题】:try-with-resource close sequence : FileInputStream close executed three timestry-with-resource 关闭序列:FileInputStream 关​​闭执行了 3 次
【发布时间】:2015-06-02 18:56:20
【问题描述】:

我正在尝试在 OS X 上使用 Java 8 的简单 try-with-resource 示例。 我看到一些奇怪的行为。首先,以下是我正在运行的代码:

 public void test() {

        try( FileInputStream fin = new FileInputStream("/tmp/test");
             FileOutputStream fout = new FileOutputStream("/tmp/test1")
                ){

            System.out.println("Nothing here");
            System.out.println("Nothing here");
        }catch (Exception e) {
            System.err.println("Error "  + e);
        }
    }

应用程序运行良好,并以预期的两倍打印Nothing here。 当我在调试模式(IntelliJ 想法)下运行它时,执行在FileInputSteam::close() 处暂停两次,然后在FileOutputStream::close() 处暂停,然后在FileInputStream::close() 处再次暂停——为了检查这种行为的来源,我查看了.class通过 jad-gui 文件。它显示以下代码:

public void test()
  {
    try
    {
      FileInputStream fin = new FileInputStream("/tmp/test");Throwable localThrowable6 = null;
      try
      {
        FileOutputStream fout = new FileOutputStream("/tmp/test1");Throwable localThrowable7 = null;
        try
        {
          System.out.println("Nothing here");
          System.out.println("Nothing here");
        }
        catch (Throwable localThrowable1)
        {
          localThrowable7 = localThrowable1;throw localThrowable1;
        }
        finally {}
      }
      catch (Throwable localThrowable4)
      {
        localThrowable6 = localThrowable4;throw localThrowable4;
      }
      finally
      {
        if (fin != null) {
          if (localThrowable6 != null) {
            try
            {
              fin.close();
            }
            catch (Throwable localThrowable5)
            {
              localThrowable6.addSuppressed(localThrowable5);
            }
          } else {
            fin.close();
          }
        }
      }
    }
    catch (Exception e)
    {
      System.err.println("Error " + e);
    }
  }

这更令人困惑。

为什么反编译后的代码没有显示任何调用 FileOutputStream::close() - 这是 jd-gui 的问题吗?

为什么在调试过程中控件会先转到两次 FileInputStream::close()?这是一些错误还是它应该如何工作?

【问题讨论】:

  • 这是一个很好的问题。我不知道,但如果我不得不猜测,我会认为 FileOutputStream 在其自己的关闭过程中内部关闭 FileInputStreams。有没有人看过它的来源?您拥有的所有数据都是类,而不是特定实例。
  • @MichaelEricOberlin FileOutputStream 如何以及为什么会关闭它甚至看不到的FileInputStream
  • 你的反编译器一定是错的。以下是 IntelliJ 自己的反编译器如何反编译您的代码:gist.github.com/jnizet/6bbd5a1efc994438a3d6
  • @JBNizet - 感谢您的链接。看起来像 JD GUI 的问题。我会进一步调试,看看我是否能弄清楚为什么会有额外的关闭电话。

标签: java debugging java-7 try-with-resources


【解决方案1】:

查看@jb-nizet 的评论,您的反编译器没有显示正确的内容,这解释了您的问题 1。

对于问题 2,请查看调试器中的 Stream.path 变量。在我的系统上,这不是您的 Streams openend,而是 Java 8 内部文件,例如“/opt/Oracle_Java/jdk1.8.0_40/jre/lib/tzdb.dat”、“/opt/Oracle_Java/jdk1.8.0_40/jre/ lib/meta-index”和类本身。但我只有一个输入流“/tmp/test”和一个输出流“/tmp/test1”的调用。

【讨论】:

  • 谢谢!我根据您的回答更仔细地研究了事情。调试时,两个文件输入流被关闭,这与代码无关。正如您提到的 tzdb.datMyTest.class 文件,它是 java 内部的。以前这让我很困惑,因为我认为所有这些都代表我的代码而关闭。鉴于此,结束序列按预期工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-18
  • 1970-01-01
  • 1970-01-01
  • 2019-03-12
相关资源
最近更新 更多