2013-09-01 2 views
0

Я читаю много XML-файлов в java и преобразовываю их в JSON и записываю их обратно в файловую систему. Общий размер папки XML составляет около 100 ГБ, а размер одного файла XML может составлять около 100 МБ. Размер JVM-памяти установлен 512 МБ. Вот цикл для чтения и записи файлов:Исключение в потоке «main» java.lang.OutOfMemoryError

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 loop, они находятся в памяти, и они не собираются с мусором. Как я могу заставить этот код работать. Благодаря

+0

Вы можете попробовать использовать несколько потоков, проходящих параллельно. Каждый поток работает в разных файлах, поэтому они не будут мешать друг другу. Это, конечно, требует большего использования памяти – gerrytan

+0

Можете ли вы проверить, является ли проблема единственным файлом? Перемещение 'System.out.println()' для входного файла перед обработкой должно указывать, какой файл последний, когда происходит OOM; затем изменение кода для запуска только в том, что один файл скажет, является ли это проблемой одного файла или что-то еще. – ash

ответ

0

Я думаю, что есть некоторые вещи, которые вы можете попробовать

  1. можно вызвать вручную сборщик мусора, System.gc(), если я правильно помню.
  2. Вы можете использовать профилировщик (как тот, который снабжен Netbeans), чтобы увидеть, где происходит утечка памяти.
  3. Вы также можете посмотреть на слабые ссылки/фантомные ссылки, но мои знания об этом низки.
+0

Маловероятно, что принудительная сборка мусора повлияет на исключение из памяти. Сбор мусора будет выполняться до того, как будет выбрано исключение из памяти. Однако это не невозможно для этого. – ash

2

Если вы внимательно изучаете код, утечки памяти очевидны, поэтому проблема может быть вызвана одним входным файлом, который слишком велик для обработки.

Настройка размера кучи JVM на 1024 может работать очень медленно, если это больше, чем доступная память на сервере, так как это приведет к замене, что является дисковым вводом-выводом и очень медленным.

Единственный способ устранить проблему, вызванную одним входным файлом, с использованием того же оборудования, - это изменить обработку в некотором роде, которая использует меньше памяти. Например, с помощью инструмента преобразования xml-to-json, который использует меньше памяти или находит способ разделить XML на куски и вернуть его вместе; но это не тривиально.

Вы можете перейти на более крупное оборудование. Обязательно используйте 64-битную O/S и 64-разрядную версию java, если это возможно.

Смежные вопросы