文件不能被删除,因为JVM拥有它 - 这是一个棘手的问题 [英] File cannot be deleted because the JVM holds it - a tricky one

查看:841
本文介绍了文件不能被删除,因为JVM拥有它 - 这是一个棘手的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的帖子有点太长了,对不起。这里是一个总结:


  • 磁盘上的文件不能被删除(JVM保存文件错误)。在从java代码中删除时以及尝试从Windows手动删除文件时都是如此。

  • 该文件的所有流都是关闭的,并设置为空。所有文件对象都设置为空。
  • 程序在这一点上什么都不做;但等待30分钟让我从Windows删除文件。奇怪的。该文件不再被java使用了吗?此外,由于程序中没有任何事情发生,它表明它不能是我忘记的某些流(加上,我三重选中没有打开任何东西)。
  • 调用System.gc()似乎在工作时文件很小。当他们达到大约20MB时没有帮助。





<编辑2] - 我试过了编写一些基本的代码来解释,但它很棘手。我很抱歉,我知道这很难回答。当然,我可以编写如何打开和关闭流:

  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;

如果我使用了一个文件对象:

 文件f =新文件(C:\\folder\\myFile.txt); 
//使用它...
f = null;

基本代码,我知道。但这基本上就是我所做的。
我知道一个事实 我以这种确切的方式关闭了所有流。
我知道一个事实 在程序中没有任何事情发生,在30分钟内我无法删除文件,直到我奇迹般地出现。



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






对不起,我没有提供任何特定的代码,因为我无法精确定位问题(不完全特定的代码相关)。在任何情况下,都是这样的:

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



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

事情是 - 这很奇怪 - 有时会起作用,有时却不起作用。即使手动,去文件夹,并尝试通过Windows删除文件,给了我该文件是由JVM打开消息。



现在,我很好意识到保持对文件的各种流的引用可以防止我删除它。那么现在过去:)
我已确保所有流都关闭。我甚至将它们的值设置为null,包括我使用的任何File对象(尽管它不应该有任何区别)。全部设置为空,全部关闭。并且生成它们全部的线程 - 读/写线程 - 它会在run()方法结束时终止。



通常,如果我等待30分钟左右,当JVM仍在运行时,我可以从Windows手动删除文件。该错误神奇消失。当JVM关闭时,我可以马上立即删除文件。



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



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



我错过了什么?为什么30分钟后文件可删除(当时什么都没有发生 - 我的代码中没有)。我是否缺少一些温和的引用/垃圾收集thingy?

解决方案

你说如果发生了IO异常,它会立即打印出来,这可能是真的,但鉴于不可思议的事情发生,让我们更好地怀疑它。



我会首先确保所有东西总是关闭,然后我会关心相关逻辑(日志记录,退出,...)。

无论如何,你所做的并不是如何资源应该被管理。 上面的答案不完全更正。无论如何,尝试与资源是(除了@ lombok.Cleanup)关于唯一的方式,清楚地表明没有任何事情可以保持开放。其他的更复杂,更容易出错。我强烈建议在任何地方使用它。这可能是一些工作,但它也迫使你重新检查所有关键的代码块。



诸如取消引用和调用GC应该不会有帮助。 。如果他们似乎这样做,这可能是一个机会。



一些想法:


  • 是否使用内存映射文件?

  • 是否确定 System.exit 未被安全管理员禁用? / li>
  • 您正在运行防病毒软件吗?他们喜欢在写入文件后立即扫描文件。



顺便说一句,锁定文件是WOW从未为我开始的一个原因。有时候这些锁在罪魁祸首消失之后仍然存在很久,至少根据我可以使用的工具而定。


My post got a little too long, sorry. Here is a summary:

  • File on disk cannot be deleted ("the JVM holds the file" error). both when deleting from the java code and when trying to manually delete the file from windows.
  • All streams to that file are closed and set to null. All file objects set to null.
  • The program does nothing at that point; but waiting 30 minutes allows me to deleted the file from windows. Weird. Is the file not used by java anymore? Plus, since nothing happens in the program, it indicates it cannot be some stream I forgot (plus, I triple checked nothing is open).
  • Invoking System.gc() seemed to work when files were small. Did not help when they got to about 20MB.

[EDIT2] - I tried writing some basic code to explain, but its tricky. I am sorry, I know it's difficult to answer like that. I can however write how I open and close streams, of course:

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;

If I've used a file object:

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

Basic code, I know. But this is essentially what I do. I know for a fact I've closed all streams in this exact way. I know for a fact that nothing happens in the program in that 30-minutes interval in which I cannot delete the file, until I somehow magically can.

thank you for your input even without the coherent code. I appreciate that.


Sorry for not providing any specific code here, since I can't pinpoint the problem (not exactly specific-code related). In any case, here is the thing:

I have written a program which reads, writes and modifies files on disk. For several reasons, the handling of the read/write is done in a different thread, which is constantly operating.

At some point, I am terminating the "read/write" thread, keeping only the main thread - it waits for input from a socket, totally unrelated to the file, and does nothing. Then, I try to delete the file (using either File.delete(), even tried nio.Files delete option).

The thing is - and it's very weird - sometimes it works, sometimes it doesn't. Even manually, going to the folder and trying to delete the file via windows, gives me the "The file is open by the JVM" message.

Now, I am well aware that keeping references from all kinds of streams to the file prevents me from deleting it. Well past that by now :) I have made sure that all streams are closed. I even set their values to null, including any "File" objects I have used (even though it shouldn't make any difference). All set to null, all closed. And the thread which generates all of them - the "read/write" thread - well, it's terminated since it got the the end of its run() method.

Usually, if I wait about 30 minutes, while the JVM still operates, I can delete the file manually from windows. The error magically disappears. When the JVM is closed, I can always delete the file right away.

I am lost here. Tried specifically invoking System.gc() before trying to delete the file, even called it like 10 times (not that it should matter). Sometimes it helped, but on other occasions, for example, when the file got larger (say 20MB), that didn't help.

What am I missing here? Obviously, this couldn't be my implicit fault (not closing some stream), since the read/write thread is dead, the main thread awaits something unrelated (so the program is at a "standstill"), I have explicitly closed all streams, even nullified the references (inStream = null), invoked the garbage collector.

What am I missing? Why is the file "deletable" after 30 minutes (nothing happens at that time - not something in my code). Am I missing some gentle reference/garbage collection thingy?

解决方案

What you're doing just calls for problems. You say that "if an IOexception occurred, it is printed immediately" and it may be true, but given that something inexplicable happens, let's better doubt it.

I'd first ensure that everything gets always closed, and then I'd care about related logic (logging, exiting, ...).

Anyway, what you did is not how resources should be managed. The answer above is not exactly correct either. Anyway, try-with-resources is (besides @lombok.Cleanup) about the only way, clearly showing that nothing gets ever left open. Anything else is more complicated and more error-prone. I'd strongly recommend using it everywhere. This may be quite some work, but it also forces you to re-inspect all the critical code pieces.

Things like nullifying references and calling the GC should not help... and if they seem to do, it may be a chance.

Some ideas:

  • Are you using memory mapped files?
  • Are you sure System.exit is not disabled by a security manager?
  • Are you running an antivirus? They love to scan files just after they get written.

Btw., locking files is one reason why the WOW never started for me. Sometimes the locks persisted long after the culprit was gone, at least according to tools I could use.

这篇关于文件不能被删除,因为JVM拥有它 - 这是一个棘手的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆