在我的程序中,关闭java.util.RandomAccessFile有时需要45秒(好吧,几乎完全是:在44.998和45.003秒之间)。该程序创建和关闭许多小文件。通常关闭文件非常快(在0到0.1秒之间)。如果我调试程序,它将停留在本机方法RandomAccessFile.close0。
使用FileOutputStream而不是RandomAccessFile时也会出现同样的问题(在这种情况下,程序在本机方法FileOutputStream.close0中被阻止)。
有人知道那可能是什么吗?你可以在你的系统上重现这个问题(我只能在Mac上重现它,而不是在Windows XP上重现;我还没有在Linux上测试过)?
更新2:
这似乎只发生在Mac OS X上。我使用的是JDK 1.6.0_22-b04。它发生在32位和64位上。在Windows XP上似乎没有发生。
我的测试用例是:
import java.io.File;
import java.io.RandomAccessFile;
public class TestFileClose {
public static void main(String... args) throws Exception {
for (int i = 0; i < 100000; i++) {
String name = "test" + i;
RandomAccessFile r = new RandomAccessFile(name, "rw");
r.write(0);
long t = System.currentTimeMillis();
r.close();
long close = System.currentTimeMillis() - t;
if (close > 200) {
System.out.println("closing " + name +
" took " + close + " ms!");
}
if (i % 2000 == 0) {
System.out.println("test " + i + "/100000");
}
new File(name).delete();
}
}
}
我机器上的输出示例:
test 0/100000
test 2000/100000
test 4000/100000
test 6000/100000
test 8000/100000
test 10000/100000
closing test10030 took 44998 ms!
test 12000/100000
test 14000/100000
test 16000/100000
closing test16930 took 44998 ms!
test 18000/100000
test 20000/100000
答案 0 :(得分:7)
可以在我的计算机上安装McAfee防病毒软件。我不得不安装它......但是如果我禁用了按访问扫描,问题也会出现。
要想验证它不是防病毒软件,有人会在他的机器上重复测试(没有防病毒软件)并且我猜测会遇到同样的问题。
答案 1 :(得分:0)
可能是垃圾收集活动,由打开/关闭大量RandomAccessFile
个对象触发; 45秒内可能没有任何魔力 - 它可能只是你的机器上的JVM遍历堆清理对象以释放的时间。话虽如此,45秒是非常长的GC暂停;我最近工作的一个应用程序总是遭受大约11秒的完整GC。
尝试使用 JConsole 或 JVisualVM 监控您的程序,或者在启动程序时尝试添加以下选项:
-verbose:gc -Xloggc:gc.log -XX:+PrintGCDetails -XX:+PrintGCTimeStamps
然后查看生成的 gc.log 文件,了解应用程序的停止时间;如果您设置代码以打印时间戳,则可以将close()
行为与特定的GC活动联系起来:
...
if (close > 200) {
System.out.println(new Date());
System.out.println("closing " + name +
" took " + close + " ms!");
}
...
如果它与GC相关,则在 gc.log 文件中,您将在程序输出文件的时间戳附近查找完整垃圾收集和/或应用程序停止时间。
修改堆设置(-Xmx=...
和XX:MaxPermSize=...
)可能会为您提供完全不同的个人资料。
另一方面,如果它是一个临时文件,请尝试使用File file = File.createTempFile(prefix, suffix)
并将其传递到RandomAccessFile
- 这可能会在OS上创建/ var / tmp(或其所谓的任何文件)中的文件X,因此使用内存文件系统而不是基于磁盘的文件系统。