0

名前付きパイプを介してDBにデータをロードするプログラムがあります。非常にクールです。このプログラムは約 2 年間実行されており、テキスト ファイルまたは gzip を受け入れます。

しかし、ロードするzipが表示されたので、改善したいと思います。しかし、これを機能させることはできません。OutOfMemoryError が発生しています。

(もちろん、私はこれを -Xms512M -Xmx2048M を使用して呼び出しています)

以下は、InputStream を取得する方法です。

PipeLoader.java

protected BufferedReader getBufferedReader(File file, String compression) throws Exception {
    BufferedReader bufferedReader = null;

    if(compression.isEmpty())   {
        bufferedReader = new BufferedReader(new FileReader(file), BUFFER);
    } else if(compression.equalsIgnoreCase("gzip")) {
        InputStream fileStream = new FileInputStream(file);
        InputStream gzipStream = new GZIPInputStream(fileStream);

        // Works fine
        Reader reader = new InputStreamReader(gzipStream);
        bufferedReader = new BufferedReader(reader, BUFFER);
    } else if(compression.equalsIgnoreCase("zip")){
        InputStream fileStream = new FileInputStream(file);
        ZipInputStream zipStream = new ZipInputStream(fileStream);
        zipStream.getNextEntry(); // For testing purposes I'm getting only the first entry

        Reader reader = new InputStreamReader(zipStream); // Works only with small zips
        bufferedReader = new BufferedReader(reader, BUFFER);
    }

    return bufferedReader;
}

TrueVFSライブラリでも試してみました。

// The same: works with small zip files, OutOfMemoryError with big zip files
TFile tFile = new TFile(file);
TFileInputStream tfis = new TFileInputStream(new TFile(tFile.getAbsolutePath(), tFile.list()[0]));

Reader reader = new InputStreamReader(tfis);
bufferedReader = new BufferedReader(reader, BUFFER);

はい、すべてを適切に閉じています (覚えておいてください、gz で動作します!)。

この場合、プレーンテキストファイルを 1 つだけ含む zip ファイルをロードする必要があります (zip で最大 4GB、unzip で最大 35GB)。

最初のファイルで、開始から 1 分もかからずに OutOfMemoryError が発生しました。

PS .: これはRead a huge Zip file in java - Out of Memory Errorからの複製ではありません。彼には、zip 内から小さなファイルをそれぞれ読み取るオプションがありましたが、大きなファイルは 1 つしかありません。

-XX:+HeapDumpOnOutOfMemoryError で実行し、Memory Analyser で .hprof ファイルを読みましたが、あまり役に立ちません =/:

MemoryAnalyser.png

助けてください。

4

1 に答える 1

1

スタックトレースを見ると、BufferedReader.readLine()最終的に非常に大きな配列が作成され、OutOfMemoryError.

readLine()改行に到達するまで入力を読み取り続けるため、これは、圧縮された入力ファイルに改行がない (または非常に少ない) ことを示します。

于 2014-04-16T12:53:14.193 に答える