0

我已阅读该文件是非托管资源,不会被垃圾收集器处理。

如果您不关闭文件,我确信如果没有引用该文件,则对该文件的引用将被垃圾收集。那么究竟是什么保持开放?它是操作系统级别的东西吗?就像 SQL 连接一样,我知道操作系统保持 TCP 端口打开,您最终可能会用完端口。但是,在文件的情况下保持打开状态的是什么?

4

2 回答 2

4

finalize()由于包装资源的类中的方法,垃圾收集器最终可能会释放操作系统资源。但是,在未来某个时间释放操作系统资源还不够好。

具体有两个问题:

  1. 您可以在 GC 有机会运行之前很久就达到操作系统限制。达到这样的限制不会像堆空间耗尽那样触发自动 GC。
  2. 即使您释放操作系统资源,您可能仍然有不会被刷新的应用程序级缓冲区。

例如,Debian Linux 的默认打开文件限制为 1024,以防止行为不端的程序对自身进行 DoS 攻击。考虑这个程序,每次迭代最好只使用一个 FD:

import java.io.*;
class Foo {
  public static void main(String[] args) throws Exception {
    for(int i=0; i<2000; i++) {
      FileInputStream fis = new FileInputStream("Foo.java");
    }
  }
}

运行它时会发生以下情况:

$ java Foo
Exception in thread "main" java.io.FileNotFoundException: Foo.java (Too many open files)
        at java.io.FileInputStream.open0(Native Method)
        at java.io.FileInputStream.open(FileInputStream.java:195)
        at java.io.FileInputStream.<init>(FileInputStream.java:138)
        at java.io.FileInputStream.<init>(FileInputStream.java:93)
        at Foo.main(Foo.java:5)

如果您手动关闭了文件,则不会发生这种情况。

这是另一个将字符串写入文件,然后将其读回的程序示例:

import java.io.*;
class Foo {
  static void writeConfig(String s) throws IOException {
    BufferedWriter fw = new BufferedWriter(new FileWriter("config.txt"));
    fw.write(s);
    System.out.println("Successfully wrote config");
  }
  static String readConfig() throws IOException {
    BufferedReader reader = new BufferedReader(new FileReader("config.txt"));
    return reader.readLine();
  }
  public static void main(String[] args) throws Exception {
    writeConfig("Hello World");
    System.gc();  // Futile attempt to rely on the GC
    String input = readConfig();
    System.out.println("The config string is: " + input);
  }
}

这是你得到的:

$ java Foo
Successfully wrote config
The config string is: null

写入的字符串没有进入文件。如果您关闭了 BufferedWriter,这将不是问题。

于 2019-04-09T17:36:22.727 回答
0

如果不再有对打开文件的引用,垃圾收集器肯定会清除内存。但是,它只会在收集器运行时发生。在那之前,该资源将保留在内存中。

但是,关闭它是个好主意,因为如果您有很多这样的文件处于打开状态,如果有足够多的线程生成打开文件但您不关闭它们,您就有内存不足的风险 - 最终命中GC 启动前的 JVM 内存最大大小。

于 2019-04-09T17:00:34.703 回答