线程“main”java.lang.outofmemoryerror中出现异常

cgfeq70w  于 2021-06-03  发布在  Hadoop
关注(0)|答案(2)|浏览(482)

我正在阅读大量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循环中创建file、stringbuilder和bufferedreader,所以它们都在内存中,不会被垃圾收集。我怎样才能使这个代码工作。谢谢

h9vpoimq

h9vpoimq1#

仔细看代码,没有明显的内存泄漏,因此问题很可能是由于单个输入文件太大而无法处理造成的。
如果jvm堆大小超过服务器上的可用内存,那么将jvm堆大小设置为1024可能会运行得非常慢,因为这会导致交换,即磁盘i/o,而且非常慢。
消除单个输入文件(使用相同的硬件)引起的问题的唯一方法是以某种使用较少内存的方式更改处理。例如,使用一个使用较少内存的xml到json转换工具,或者找到一种方法将xml拆分成多个片段并重新组合起来;这可不是小事。
你可以转向更大的硬件。如果可能,请确保使用64位o/s和64位版本的java。

e4yzc0pl

e4yzc0pl2#

我想有些事情你可以试试
如果我没记错的话,可以手动调用垃圾收集器system.gc()。
您可以使用探查器(如netbeans提供的那样)查看内存泄漏的位置。
你也可以查看弱引用/幻象引用,但我对它们的了解很少。

相关问题