11

私のプログラムでは、java.util.RandomAccessFile を閉じるのにちょうど 45 秒かかることがあります (ほぼ正確に言えば、44.998 秒から 45.003 秒の間です)。プログラムは、多数の小さなファイルを作成して閉じます。通常、ファイルのクローズは非常に高速です (0 ~ 0.1 秒)。プログラムをデバッグすると、ネイティブ メソッド RandomAccessFile.close0 でスタックします。

同じ問題は、RandomAccessFile の代わりに FileOutputStream を使用した場合にも発生します (この場合、プログラムはネイティブ メソッド FileOutputStream.close0 でブロックされます)。

誰かがそれが何であるか考えていますか? お使いのシステムで問題を再現できますか (Windows XP ではなく Mac でのみ再現できます。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
4

2 に答える 2

8

私の場合、それは私のマシンにインストールされた McAfee アンチウイルスであることが判明しました。私はそれをインストールしなければなりませんでした(会社の方針)...

オンアクセス スキャンを無効にした場合にも問題が発生しました。

于 2011-01-22T17:48:55.517 に答える
0

多数のオブジェクトを開いたり閉じたりすることによってトリガーされるガベージ コレクション アクティビティである可能性があります。RandomAccessFile45 秒について魔法のようなことは何もないかもしれません。これは、マシン上の JVM がオブジェクトを解放するためにヒープ スカベンジングを走査するのにかかる時間にすぎない可能性があります。そうは言っても、45 秒というのは非常に長い GC 一時停止です。私が最近取り組んだ 1 つのアプリケーションでは、常に約 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 X の /var/tmp (またはそれが呼び出されたもの) にファイルが作成される可能性があるため、代わりにメモリ内ファイルシステムを使用します。ディスクベースのファイル システム。

于 2011-01-22T17:26:25.867 に答える