Java 无法删除该文件,因为JVM持有它-这是一个棘手的问题

Java 无法删除该文件,因为JVM持有它-这是一个棘手的问题,java,file,stream,garbage-collection,jvm,Java,File,Stream,Garbage Collection,Jvm,对不起,我的帖子有点太长了。以下是总结: 无法删除磁盘上的文件(“JVM保存文件”错误)。从java代码中删除文件时,以及尝试从windows手动删除文件时 该文件的所有流都将关闭并设置为null。所有文件对象都设置为空 程序在这一点上什么也不做;但是等待30分钟可以让我从windows中删除该文件。奇怪的java不再使用该文件了吗?另外,由于程序中没有发生任何事情,这表明它不可能是我忘记的某个流(另外,我三次检查没有打开) 当文件很小时,调用System.gc()似乎可以工作。当它们达到20

对不起,我的帖子有点太长了。以下是总结:

  • 无法删除磁盘上的文件(“JVM保存文件”错误)。从java代码中删除文件时,以及尝试从windows手动删除文件时

  • 该文件的所有流都将关闭并设置为null。所有文件对象都设置为空
  • 程序在这一点上什么也不做;但是等待30分钟可以让我从windows中删除该文件。奇怪的java不再使用该文件了吗?另外,由于程序中没有发生任何事情,这表明它不可能是我忘记的某个流(另外,我三次检查没有打开)
  • 当文件很小时,调用System.gc()似乎可以工作。当它们达到20MB左右时没有帮助

[EDIT2]-我试着写一些基本代码来解释,但这很棘手。对不起,我知道这样回答很难。当然,我可以写下如何打开和关闭流:

BufferedWriter bw = new BufferedWriter(new FileWriter(new File("C:\\folder\\myFile.txt")));
for(int i = 0; i < 10; i++)
{
    bw.write("line " + i);
    bw.newLine();
}
bw.close();
bw = null;
基本代码,我知道。但这基本上就是我所做的。 我知道事实上我已经用这种方式关闭了所有的流。 我知道一个事实,在我不能删除文件的30分钟间隔内,程序中没有任何事情发生,直到我奇迹般地删除文件

感谢您的输入,即使没有连贯的代码。 我很感激


很抱歉,这里没有提供任何特定代码,因为我无法确定问题所在(与特定代码无关)。无论如何,事情是这样的:

我写了一个程序,可以读取、写入和修改磁盘上的文件。出于几个原因,读/写操作是在一个不同的线程中完成的,该线程一直在运行

在某个时刻,我终止了“读/写”线程,只保留主线程——它等待来自套接字的输入,与文件完全无关,并且什么也不做。然后,我尝试删除该文件(使用file.delete(),甚至尝试使用nio.Files delete选项)

事情是——这很奇怪——有时有效,有时无效。即使是手动操作,转到文件夹并尝试通过windows删除该文件,也会显示“该文件已被JVM打开”消息

现在,我很清楚,保留对文件的各种流的引用会阻止我删除它。现在已经过去了:) 我已确保所有溪流都已关闭。我甚至将它们的值设置为null,包括我使用过的任何“文件”对象(尽管这不会有任何区别)。全部设置为空,全部关闭。生成所有线程的线程——“读/写”线程——由于它得到run()方法的结尾,所以它被终止

通常,如果我等待大约30分钟,而JVM仍在运行,我可以从windows手动删除该文件。错误神奇地消失了。当JVM关闭时,我总是可以立即删除该文件

我在这里迷路了。在尝试删除文件之前,尝试专门调用System.gc(),甚至调用了10次(这并不重要)。有时它会有所帮助,但在其他情况下,例如,当文件变得更大(比如20MB)时,则没有帮助

我错过了什么? 显然,这不可能是我的隐式错误(没有关闭某些流),因为读/写线程已经死了,主线程等待一些无关的东西(因此程序处于“静止状态”),我已经显式关闭了所有流,甚至取消了引用(inStream=null),调用了垃圾收集器


我错过了什么?为什么文件在30分钟后“可删除”(当时没有发生任何事情-我的代码中没有)。我是否错过了一些温和的引用/垃圾收集功能?

您是否在
尝试中关闭流…最后是
还是
尝试(a=new a())
块?如果没有,则可能无法关闭溪流。 我强烈建议对所有外部资源使用自动资源块管理(
try(A=newa())
)或
try…finally

try(BufferedWriter br = new BufferedWriter(new FileWriter(new File("C:\\folder\\myFile.txt")));
for(int i = 0; i < 10; i++)
{
  br.write("line " + i);
  br.newLine();
})
try(BufferedWriter br=new BufferedWriter(new FileWriter(新文件(“C:\\folder\\myFile.txt”));
对于(int i=0;i<10;i++)
{
br.写入(“行”+i);
br.newLine();
})

你所做的只会带来问题。你说“如果发生IOexception,它会立即被打印出来”,这可能是真的,但考虑到发生了无法解释的事情,我们最好对此表示怀疑

我首先要确保所有的东西都是关闭的,然后我要关心相关的逻辑(日志、退出等等)

无论如何,你所做的不是如何管理资源。问题是。无论如何,尝试使用资源(除了@lombok.Cleanup)大概是唯一的方法,这清楚地表明没有任何东西可以打开。其他任何东西都更复杂,更容易出错。我强烈建议在任何地方使用它。这可能是相当多的工作,但它也迫使您重新检查所有关键代码段

取消引用和调用GC之类的事情应该不会有帮助。。。如果他们真的这么做了,那可能是个机会

一些想法:

  • 您正在使用内存映射文件吗
  • 您确定安全管理器未禁用系统退出吗
  • 你在运行防病毒软件吗?他们喜欢在文件写完后立即扫描文件

顺便说一句,锁定文件是为什么我的魔兽世界从未开始的原因之一。有时,锁会在罪犯离开后很长时间内持续存在,至少根据我可以使用的工具。

好吧,试着想出一个示例代码,它肯定会帮助您更好地理解问题。好的,我会尝试,它与我描述的差不多。该文件的所有流都会关闭并设置为null。您能展示一下打开和关闭流代码吗?这里可能发生的情况是文件没有正确关闭。您将无法删除该文件。一段时间后,垃圾收集器收集该文件,并作为终结过程的一部分将其关闭。你可以删除t
try(BufferedWriter br = new BufferedWriter(new FileWriter(new File("C:\\folder\\myFile.txt")));
for(int i = 0; i < 10; i++)
{
  br.write("line " + i);
  br.newLine();
})