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 进程消耗大量内存。因为我在 for 循环中创建文件、stringbuilder 和 bufferedreader,所以它们都在内存中,它们不会被垃圾收集。我怎样才能使这个代码工作。谢谢

4

2 回答 2

2

仔细查看代码,没有明显的内存泄漏,因此问题可能是由单个输入文件引起的,该文件太大而无法处理。

将 JVM 堆大小设置为 1024 如果超过服务器上的可用内存,可能会运行非常缓慢,因为这会导致交换,即磁盘 I/O 并且非常慢。

使用相同硬件消除由单个输入文件引起的问题的唯一方法是以某种使用较少内存的方式更改处理。例如,使用占用较少内存的 xml 到 json 转换工具,或者找到一种方法将 XML 拆分为多个片段并重新组合在一起;不过,这不是微不足道的。

您可以迁移到更大的硬件。如果可能,请确保使用 64 位操作系统和 64 位版本的 java。

于 2013-09-02T00:30:23.273 回答
0

我认为有些事情你可以尝试

  1. 如果我没记错的话,可以手动调用垃圾收集器 System.gc()。
  2. 您可以使用分析器(与 Netbeans 一起提供的)来查看内存泄漏的位置。
  3. 您也可以查看弱引用/幻像引用,但我对这些的了解很少。
于 2013-09-02T00:27:42.223 回答