0

Javaで多くのXMLファイルを読み取り、JSONに変換してファイルシステムに書き戻しています。XML フォルダーの合計サイズは約 100Gb で、単一の XML ファイルのサイズは約 100MB になる場合があります。JVM メモリのサイズは 512Mb に設定されています。ファイルの読み取りと書き込みのループは次のとおりです。

  for(int i=0; i<fileNames.size(); i++) {

  try{
    File f = new File(File.separator+fileNames.get(i));


    BufferedReader br = new BufferedReader(new FileReader(f));

    String line;

    StringBuilder sb = new StringBuilder();

    long startTime = System.nanoTime();

    while((line=br.readLine())!= null){
        sb.append(line.trim());
    }


    String jsonData = XML.toJSONObject(sb.toString()).toString(0);

    String outputFilename = fileNames.get(i).split("\\.")[0]+".json";

    Path jsonFilePath = new Path(jsonPath+File.separator+outputFilename);

    FSDataOutputStream out = fileSystem.create(jsonFilePath);
    out.writeChars(jsonData);
    byte[] b = jsonData.getBytes("UTF-8");

    out.close();
    br.close();

    long endTime = System.nanoTime();
    double executionTime = (double)(endTime - startTime) / 1000000000.0;

    System.out.println("Input file : "+fileNames.get(i)+" - "+(double)(f.length()/1000) + " kb");
    System.out.println("Output file : "+outputFilename+" - "+(double)(b.length/1000) + " kb"+" in "+executionTime + " seconds");
    System.out.println("--------------------------------------------------");

}catch(IOException ioe){
    ioe.printStackTrace();
}catch (JSONException je) {
    System.out.println(je.toString());
}catch(Exception e){
    e.printStackTrace();
}

    }

しばらく実行した後、このプログラムは : をスロー Exception in thread "main" java.lang.OutOfMemoryError: Java heap spaceします。JVM メモリを -Xmx1024 に増やすと、プログラムの実行が非常に遅くなり、Java プロセスが大量のメモリを消費します。ファイル、stringbuilder、および bufferedreader を for ループで作成しているため、これらはメモリ内にあり、ガベージ コレクトされません。このコードを機能させるにはどうすればよいですか。ありがとう

4

2 に答える 2

2

コードを注意深く見ると、明らかなメモリ リークは見られないため、処理するには大きすぎる 1 つの入力ファイルが問題の原因である可能性が高いと思われます。

JVM ヒープ サイズを 1024 に設定すると、サーバーで使用可能なメモリを超える場合、実行が非常に遅くなる可能性があります。これは、ディスク I/O であるスワッピングが発生し、非常に遅くなるためです。

単一の入力ファイルが原因で発生する問題を解消する唯一の方法は、同じハードウェアを使用して、より少ないメモリを使用する方法で処理を変更することです。たとえば、メモリの使用量が少ない xml から json への変換ツールを使用するか、XML を分割して元に戻す方法を見つけます。しかし、それは些細なことではありません。

より大きなハードウェアに移行できます。可能であれば、64 ビット O/S および 64 ビット バージョンの Java を使用してください。

于 2013-09-02T00:30:23.273 に答える
0

いろいろ試してみるといいと思います

  1. 私の記憶が正しければ、手動でガベージ コレクター System.gc() を呼び出すことができます。
  2. プロファイラー (Netbeans で提供されるプロファイラー) を使用して、メモリ リークが発生している場所を確認できます。
  3. 弱い参照/ファントム参照も調べることができますが、それらに関する私の知識は低いです。
于 2013-09-02T00:27:42.223 に答える