无法删除文件,因为JVM持有它 - 一个棘手的

时间:2016-05-16 04:02:41

标签: java file stream garbage-collection jvm

我的帖子有点太长了,抱歉。以下是摘要:

  • 无法删除磁盘上的文件(“JVM保存文件”错误)。从java代码中删除时以及尝试从Windows手动删除文件时。
  • 该文件的所有流都已关闭并设置为null。所有文件对象都设置为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;

如果我使用了文件对象:

File f = new File("C:\\folder\\myFile.txt");
// use it...
f = null;

基本代码,我知道。但这基本上就是我所做的。 我知道的事实我已经以这种方式关闭了所有流。 我知道一个事实在30分钟的时间间隔内我没有删除文件的程序中没有任何事情发生,直到我不知何故神奇地可以。

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

很抱歉这里没有提供任何特定代码,因为我无法查明问题(与具体代码无关)。无论如何,这就是事情:

我编写了一个程序,可以读取,写入和修改磁盘上的文件。由于多种原因,读/写的处理是在不同的线程中完成的,该线程一直在运行。

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

事情是 - 而且非常奇怪 - 有时它起作用,有时它不起作用。甚至手动,转到文件夹并尝试通过Windows删除文件,给我“文件由JVM打开”消息。

现在,我很清楚将各种流的引用保存到文件会阻止我删除它。那个过去,现在:) 我确保所有流都关闭了。我甚至将它们的值设置为null,包括我使用的任何“文件”对象(即使它不应该有任何区别)。全部设置为null,全部关闭。生成所有这些线程的线程 - “读/写”线程 - 好吧,它终止了,因为它得到了run()方法的结束。

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

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

我在这里缺少什么? 显然,这可能不是我的隐含错误(不关闭某些流),因为读/写线程已经死了,主线程等待不相关的东西(所以程序处于“停顿”状态),我已经明确关闭了所有流,甚至使引用无效(inStream = null),调用垃圾收集器。

我错过了什么? 30分钟后为什么文件“可删除”(当时没有任何反应 - 我的代码中没有任何内容)。我错过了一些温和的参考/垃圾收集吗?

2 个答案:

答案 0 :(得分:2)

你正在做的只是要求解决问题。你说&#34;如果发生了IOexception,它会立即打印出来#34;这可能是真的,但考虑到莫名其妙的事情,让我们更好地怀疑它。

我首先确保所有内容始终关闭,然后我关心相关逻辑(记录,退出,......)。

无论如何,你所做的并不是如何管理资源。 answer abovenot exactly correct either。无论如何,尝试资源是(除了@ lombok.Cleanup)关于唯一的方式,清楚地表明没有任何东西永远敞开。其他任何事情都更复杂,更容易出错。我强烈建议到处使用它。这可能是一些工作,但它也会迫使您重新检查所有关键代码。

无效引用和调用GC这样的事情应该无济于事......如果他们似乎这样做,那可能是一个机会。

一些想法:

  • 您使用的是内存映射文件吗?
  • 您确定安全管理员未禁用System.exit吗?
  • 您是否正在运行防病毒软件?他们喜欢在写完文件后立即扫描文件。

顺便说一句,锁定文件是WOW从未为我开始的原因之一。在罪魁祸首消失之后,有时锁定会持续很长时间,至少根据我可以使用的工具。

答案 1 :(得分:0)

您是否在try...finallytry(A a = new A())区块中关闭了您的信息流?如果不是,则可能不会关闭流。 我强烈建议对所有外部资源使用自动资源块管理(try(A a = new A()))或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();
})