如何诊断 File.delete() 返回 false / 查找未关闭的流?

2022-09-04 22:59:11

我正在使用第三方JPEG / EXIF操作库(Mediautil),这让我有些头疼。我想更改映像的 EXIF 数据。为此,我需要将更新后的版本写入临时文件,删除原始文件,然后将临时文件重命名为原始名称。

我的问题是调用失败并返回,大概是因为库仍然以某种方式打开它 - 但是我已经做了我在API中可以找到的一切来使其关闭所有流。更糟糕的是:问题似乎与时序有关,并且发生它的单元测试有时会失败,有时不会 - 但代码不是多线程的。File.delete()false

奇怪的是,有一个库调用消除了这个问题 - 但它也删除了EXIF缩略图,我实际上并不想要。看着代码,我绝对看不到它在哪里关闭了任何可能保持打开状态的流。

有什么想法如何解决这个问题?

编辑:这是在Windows XP,Java 6上。还有一件事:我发现,如果我在打电话之前打电话,它有效 - 大概是因为它触发了一些终结器。因此,它绝对似乎是一个未关闭的流。System.gc()File.delete()


答案 1

我会在这里寻求调试器的一些帮助。快速浏览一下这些内容,就会发现唯一可能的候选者是在 .因此,在那里打一个断点,运行你的程序,并尝试触发以释放你的流。这应该给你一个答案,关于这是否是你的问题。java.iofinalize()FileOutputStreamSystem.gc()FileOutputStream.finalize()

一旦可以重现,就需要开始将实例的实例化与其最终确定相匹配。一个好的调试器将为您提供每个对象的内部JVM对象标识符,因此,如果您可以在创建OID时对其进行跟踪,并在最终确定时对其进行跟踪,那么希望您将能够将密钥调用与特定的调用new相关联。FileOutputStreamfinalizenew FileOutputStream

但是,这可能是一个漫长的过程,具体取决于应用程序的复杂程度。


答案 2

如果您使用的是 FileOutputStream,则显式关闭它允许删除该文件。

例如,代替:

File myFile = new File("test.txt");
myCustomStreamProcess(new FileOutputStream(myFile));
boolean test = myFile.delete(); //May return false

你应该做:

File myFile = new File("test.txt");
FileOutputStream fos = new FileOutputStream(myFile);
myCustomStreamProcess(fos);
fos.close(); //Allow the document to be deleted afterwards
boolean test = myFile.delete(); //Should always return true

推荐