JVM是否自动关闭文件?

Vov*_*huk 1 java jvm scala file

在某处我读到没有必要自己关闭它,只需离开它,JVM将帮助你做到这一点.这是真的吗?

假设我需要从文件中获取数据

Source.fromFile(fileName).getLines() 
Run Code Online (Sandbox Code Playgroud)

直接,没有

val source = Source.fromFile(fileName)
val lines = source.getLines()
............
source.close()
Run Code Online (Sandbox Code Playgroud)

第一种方式,我无法直接访问源并关闭它.我的JVM工作了很长时间.我需要关闭一个文件(需要关闭未使用的资源).

如果有人可以在这里留下一些链接或解释,那将是很棒的.

Ste*_*n C 5

在某处我读到没有必要自己关闭它,只需离开它,JVM将帮助你做到这一点.这是真的吗?

这部分是正确的.

如果你打开一个文件,使用它,然后删除文件或流句柄(或任何你想要调用它),然后GC找到它,然后GC将排队文件句柄对象以进行最终确定.当完成最终化时,文件处理程序的finalize()方法将释放资源; 即文件描述符.

但是,依靠GC来做这件事是个坏主意.

  • 如果可以访问文件句柄,则GC不会完成它.
  • 你有当GC要运行下一个办法知道1.
  • 当GC运行时,它不一定会收集所有的垃圾2.
  • 排队等待最终确定的对象直到GC完成后才能实际完成.(见@ Holger的评论)

把这四个东西放在一起,在GC开始收集和关闭废弃的文件句柄之前,应用程序很容易用完文件描述符.如果发生这种情况,您可能会在打开文件,目录,套接字等操作时遇到异常.

以下是您可以运行的示例(在Linux/UNIX上)以查看此情况:

import java.io.FileInputStream;

public class Test {
    public static void main(String[] args) throws Exception {
        for (int i = 0; i < 100000; i++) {
            new FileInputStream("/etc/motd");
        }
    }
}

$ javac Test.java 
$ java Test 
Exception in thread "main" java.io.FileNotFoundException: /etc/motd (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 Test.main(Test.java:6)
Run Code Online (Sandbox Code Playgroud)

1 - 典型的GC仅在堆(或堆的一部分)达到给定的"饱满度"阈值时运行.如果应用程序未分配许多对象,则可能需要很长时间才能达到阈值.

2 - 现代JVM使用分代垃圾收集器,它以不同的速率收集堆的不同部分.