线程“main”java.lang.OutOfMemoryError中的异常

时间:2013-09-01 23:38:02

标签: java exception hadoop

我正在阅读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,所以这些都在内存中并且它们不是垃圾收集的。如何使此代码工作。感谢

2 个答案:

答案 0 :(得分:2)

仔细查看代码,没有明显的内存泄漏,所以似乎问题可能是由于单个输入文件太大而无法处理。

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

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

您可以迁移到更大的硬件。如果可能,请确保使用64位O / S和64位版本的java。

答案 1 :(得分:0)

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

  1. 如果我没记错的话,可以手动调用垃圾收集器System.gc()。
  2. 您可以使用分析器(与Netbeans一起提供)来查看内存泄漏的位置。
  3. 你也可以查看弱引用/幻像引用,但我对它们的了解很少。