JVM会自动关闭文件吗?

8fq7wneg  于 2024-01-07  发布在  其他
关注(0)|答案(2)|浏览(309)

我在某个地方读到过,没有必要自己关闭它,只要离开它,JVM会帮助你做到这一点。是真的吗?
假设我需要从文件中获取数据,

  1. Source.fromFile(fileName).getLines()

字符串
直接,不

  1. val source = Source.fromFile(fileName)
  2. val lines = source.getLines()
  3. ............
  4. source.close()


首先,我不能直接访问源代码并关闭它。我的JVM工作了很长一段时间。我需要关闭一个文件(需要关闭未使用的资源)。
如果有人能在这里留下一些链接或解释,那就太好了。

gg58donl

gg58donl1#

我在某个地方读到过,没有必要自己关闭它,只要离开它,JVM会帮助你做到这一点。是真的吗?
有一部分是真的。
如果你打开一个文件,使用它,然后删除文件或流句柄(或任何你想叫它的东西),并且GC找到它,那么GC将把文件句柄对象排队等待终结。当终结发生时,文件处理程序的finalize()方法将释放资源;即文件描述符。
但是,依赖GC来完成这项工作是一个坏主意。

  • 如果一个文件句柄(仍然)是可访问的,那么GC不会将其排队等待终结。
  • 您无法知道GC何时运行next 1。
  • 当GC运行时,它不一定收集 * 所有 * 的垃圾2(因此队列 * 所有 * 丢失的文件句柄)。
  • 排队等待终结的对象直到GC完成后才真正被终结。

如果把这四点放在一起,那么在GC开始收集和关闭废弃的文件句柄之前,应用程序很容易就用完了文件描述符。如果发生这种情况,那么在打开文件、目录、套接字等的操作中很可能会出现异常。
这里有一个例子,你可以运行(在Linux / UNIX上)来看到这一切发生:

  1. import java.io.FileInputStream;
  2. public class Test {
  3. public static void main(String[] args) throws Exception {
  4. for (int i = 0; i < 100000; i++) {
  5. new FileInputStream("/etc/motd");
  6. }
  7. }
  8. }
  9. $ javac Test.java
  10. $ java Test
  11. Exception in thread "main" java.io.FileNotFoundException: /etc/motd (Too many open files)
  12. at java.io.FileInputStream.open0(Native Method)
  13. at java.io.FileInputStream.open(FileInputStream.java:195)
  14. at java.io.FileInputStream.<init>(FileInputStream.java:138)
  15. at java.io.FileInputStream.<init>(FileInputStream.java:93)
  16. at Test.main(Test.java:6)

字符串
1 -典型的GC仅在堆(或堆的一部分)达到给定的“充满”阈值时运行。如果应用程序没有分配很多对象,则可能需要很长时间才能达到阈值。
现代JVM使用分代垃圾收集器,以不同的速率收集堆的不同部分。

展开查看全部
ktecyv1j

ktecyv1j2#

是的,在某种程度上这是真的,当GC在某个时候调用finalize方法时,JVM将帮助释放文件描述符(您可以尝试通过System.gc()进行验证)。
并且完全同意我们需要显式关闭InputStream,当我们不需要它时,释放文件描述符
但是如果你的应用程序不经常操作文件描述符(文件,网络IO),我们也需要关心这个吗?毕竟,有finalize方法。
是的,这是一个很好的做法,close它,明确地释放它。
而对于OP的问题很像Java的:如何安全地通过Files.lines关闭Stream。在Java中,我们可以使用try with resources来处理这个问题。但是Scala不支持这个问题,也许你可以尝试使用try ... finally来处理这个问题,比如:

  1. val reader = Source.fromFile("build.sbt").bufferedReader()
  2. try {
  3. reader.lines().forEach(line => {
  4. ...
  5. })
  6. } finally {
  7. reader.close()
  8. }

字符串

相关问题