对不起,我的帖子有点太长了。以下是摘要:
- 磁盘上的文件无法删除("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。文件删除选项)。
问题是——这很奇怪——有时有效,有时无效。即使是手动地,转到文件夹并尝试通过窗口删除文件,也会给我"文件由JVM打开"的消息。
现在,我很清楚,保留对文件的各种流的引用会阻止我删除它我已确保所有溪流都已关闭。我甚至将它们的值设置为null,包括我使用过的任何"File"对象(尽管这不会有任何区别)。全部设置为null,全部关闭。生成所有这些的线程——"读/写"线程——好吧,它被终止了,因为它得到了run()方法的末尾。
通常,如果我等待大约30分钟,而JVM仍在运行,我可以从窗口手动删除文件。错误神奇地消失了。JVM关闭时,我可以总是立即删除文件。
我在这里迷路了。在尝试删除文件之前,曾尝试过专门调用System.gc(),甚至调用了10次(这并不重要)。有时它有帮助,但在其他情况下,例如,当文件变大(比如20MB)时,它没有帮助。
我在这里错过了什么?显然,这不可能是我的隐式错误(没有关闭某些流),因为读/写线程已经死了,主线程正在等待一些不相关的东西(所以程序处于"停滞"状态),我已经显式关闭了所有流,甚至取消了引用(inStream=null),调用了垃圾收集器。
我错过了什么?为什么文件在30分钟后"可删除"(当时什么都没发生——我的代码中没有什么)。我是不是错过了一些温和的参考/垃圾收集的东西?
您所做的事情只会带来问题。你说"如果发生IOexception,它会立即打印出来",这可能是真的,但考虑到发生了一些莫名其妙的事情,我们最好对此表示怀疑
我首先要确保所有东西都是关闭的,然后我会关心相关的逻辑(日志记录、退出…)
不管怎样,你所做的并不是如何管理资源。上面的答案也不完全正确。无论如何,尝试使用资源(除了@lombok.Cleanup)是唯一的方法,这清楚地表明没有什么是开放的。其他任何事情都更复杂,也更容易出错。我强烈建议在任何地方都使用它。这可能是一项相当艰巨的工作,但它也迫使您重新检查所有关键的代码片段。
诸如取消引用和调用GC之类的事情应该没有帮助。。。如果他们真的这么做了,那可能就是一个机会。
一些想法:
- 您正在使用内存映射文件吗
- 您确定
System.exit
没有被安全管理器禁用吗 - 你正在运行防病毒软件吗?他们喜欢在文件写完后立即扫描
顺便说一下。,锁定文件是我从未开始WOW的原因之一。有时,至少根据我可以使用的工具,锁定在罪犯消失后很长一段时间仍然存在。
您是否正在关闭try...finally
或try(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();
})