java - JVM 会自动关闭文件吗?

标签 java scala file jvm

我在某处读到没必要自己关闭它,不用管它,JVM会帮你完成。是真的吗?

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

Source.fromFile(fileName).getLines() 

直接,没有

val source = Source.fromFile(fileName)
val lines = source.getLines()
............
source.close()

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

如果有人能在这里留下一些链接或解释就太好了。

最佳答案

Somewhere I read that it's unnecessary to close it by yourself, just leave it, JVM will help you do this. Is it true?

部分正确。

如果您打开一个文件,使用它,然后删除文件或流句柄(或任何您想调用它的东西),并且 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)

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

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

关于java - JVM 会自动关闭文件吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47769957/

相关文章:

java - 可用的java注释重载吗?

scala - 用Scala删除字符串中的空格

php - 读写配置文件

python - 给定一个文件,返回一个元组列表,表示 Python 文件中的行

java - 如何使用索引值拆分正则表达式

java - 解析Java中其他文本中嵌入的日期

java - 哪个版本的 oracle 瘦驱动程序与部署在 Websphere 7.0 上的应用程序一起使用

scala - 如何从 Scala 数组中选择随机元素?

scala - 为什么隐式转换在这里不起作用?

node.js - 使用 node.js 从标准输出实时读取