2014-09-06 2 views
-1

Друзья Мне нужна ваша помощь. Мне нужно обрабатывать очень большой файл с информацией (о файле весит 30 Мб). При обработке этого файла информации, Java дает мне эту ошибку:Ошибка памяти VM java, java.lang.OutOfMemoryError: Java heap space


Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space 
    at java.util.Arrays.copyOf(Arrays.java:2367) 
    at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:130) 
    at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:114) 
    at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:535) 
    at java.lang.StringBuffer.append(StringBuffer.java:322) 
    at java.io.StringWriter.write(StringWriter.java:94) 
    at java.io.Writer.write(Writer.java:127) 
    at com.sun.org.apache.xml.internal.serialize.Printer.printText(Printer.java:170) 
    ..... 

Мой код:


... 

    public Document generateXML(File file, String type) { 
     try { 
      DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
      DocumentBuilder docBuilder = dbf.newDocumentBuilder(); 

      Document document = docBuilder.newDocument(); 
      Element rootElement = document.createElement("data"); 
      document.appendChild(rootElement); 

      Element informacionElement = document.createElement("information"); 
      rootElement.appendChild(informacionElement); 

      Element entityElement = document.createElement("entity"); 
      entityElement.appendChild(document.createTextNode("ANYTHING")); 
      informacionElement.appendChild(entityElement); 

      Element entityCode = document.createElement("code"); 
      entityCode.appendChild(document.createTextNode(0000)); 
      informacionElement.appendChild(entityCode); 

      Element fileElement = document.createElement("FILENAME"); 
      fileElement.appendChild(document.createTextNode(file.getName())); 
      informacionElement.appendChild(fileElement); 

      Element detailElement = document.createElement("detail"); 
      rootElement.appendChild(detailElement); 

      Path path = Paths.get(file.getAbsolutePath()); 
      Scanner tmpFile = new Scanner(path, StandardCharsets.UTF_8.name()); 

      String[] tmpTags = keyXml.get(type); 
      int row = 1; 

      while (tmpFile.hasNextLine()) { 

       Element rowElement = document.createElement("row"); 
       filaElement.setAttribute("id", Integer.toString(row)); 

       Scanner tmpLine = new Scanner(tmpFile.nextLine()); 
       tmpLine.useDelimiter("\\|"); 
       int index = 0; 
       while (tmpLine.hasNext()) { 
        Element element = document.createElement(tmpTags[index]); 
        String text = tmpLine.next().trim(); 
        element.appendChild(document.createTextNode(text)); 
        filaElement.appendChild(element); 
        ++index; 
       } 
       detailElement.appendChild(filaElement); 
       ++fila; 
      } 
      return document; 
     } catch (ParserConfigurationException | IOException ex) { 
      Logger.getLogger(HandlerXML.class.getName()).log(Level.SEVERE, null, ex); 
     } 
     return null; 
    } 
... 

Этот код генерирует следующий XML-документ:

<data> 
     <information> 
      <entity>ANYTHING</entity> 
      <code>0000</code> 
      <filename>filename_XXX</filename> 
     </information> 
     <detail> 
      <row id="1"> 
       <tag1>0099</tag1> 
       <tag2>2014</tag2> 
       <tag3>05</tag3> 
       <tag4>0015</tag4> 
       <tag5>06</tag5> 
       <tag6>06</tag6> 
       <tag7>000000000099907</tag7> 
       <tag8>098026</tag8> 
       <tag9>00000781.40</tag9> 
       <tag10>E</tag10> 
       <tag11>000000006804750</tag11> 
       <tag12>xxx</tag12> 
       <tag13>xxxx</tag13> 
       <tag14>xxx</tag14> 
       <tag15></tag15> 
       <tag16></tag16> 
       <tag17>xx</tag17> 
       <tag18>xxx</tag18> 
       <tag19>1014</tag19> 
       <tag20>05</tag20> 
       <tag21>11111</tag21> 
       <tag22>1014</tag22> 
       <tag23>00000000000000000000</tag23> 
       <tag24>3</tag24> 
       <tag25>20101</tag25> 
       <tag26>00000000</tag26> 
       <tag27>46671</tag27> 
       <tag28>1</tag28> 
       <tag29>N</tag29> 
       <tag30></tag30> 
       <tag31></tag31> 
       <tag32>A</tag32> 
       <tag33></tag33> 
       <tag34></tag34> 
       <tag35></tag35> 
       <tag36></tag36> 
       <tag37></tag37> 
       <tag38></tag38> 
      </row> 
      ............ 
     </detail> 
    </data> 

слово, где были получены данные XML это:

** 0099 | 2014 | 05 | 0015 | 06 | 06 | 00000000003101 | 066671 | 000077777.00 | E | 0000000027 19415 | xxx | xxxxxx | xxxxxxxx | | | xxxxxx | | 1014 | 05 | 12254758 | 1014 | 00000000000000000000 | 3 | 20101 | 00000000 | 748596 | 1 | X | | | Q | | | | | **

Теперь представьте, что xml должен быть сгенерирован для 100000 строк информации, и если вам интересно, все строки должны быть преобразованы в формат XML.

Проблема, при преобразовании объекта в STRING к ДОКУМЕНТА я получаю ошибку, что я показал ранее, функция я использую для преобразования ДОКУМЕНТ в STRING является:

private static String convertDocumentToString(Document doc) { 
     TransformerFactory tf = TransformerFactory.newInstance(); 
     Transformer transformer; 
     try { 
      transformer = tf.newTransformer(); 
      StringWriter writer = new StringWriter(); 
      transformer.transform(new DOMSource(doc), new StreamResult(writer)); 
      return writer.getBuffer().toString(); 
     } 
     catch (TransformerException e) {} 
     return ""; 
    } 

Теперь эта ошибка является виртуальной памятью и временным решением Java для увеличения памяти с помощью -Xmx #### m, но я задаюсь вопросом, разрешено ли это другим путем, попробуйте обработать тип данных с помощью: String, StringBui lder и byte. Может ли кто-нибудь решить этот вопрос?

Заранее спасибо.

+0

Можете ли вы разместить свой фрагмент кода? – BatScream

+0

Пожалуйста, расскажите нам, какие операции вы делаете в этих больших файлах, могут быть способы выполнения одних и тех же операций во время «потоковой передачи» данных вместо того, чтобы иметь их в ram. –

+0

Не зная ничего о том, что вы делаете, невозможно помочь. –

ответ

2

«30 МБ» на самом деле не такой большой.

SUGGESTION: добавьте в командной строке Java: -XX:MaxPermSize=512m

ТАКЖЕ:

  • Определенно ознакомиться с профилировщика Java, jvisualvm. Он поставляется с JDK.

  • Вот хорошая статья для устранения проблемы такого рода: Anatomy of a PermGen Memory Leak

«Надежда, что помогает!

+0

Нет PermGen с Java 7. –

+0

[Java7 все еще имеет PermGen] (http://javaeesupportpatterns.blogspot.de/2011/10/java-7-features-permgen-removal.html); и он все еще может быть истощен. Главное - побудить OP точно определить, что вызывает проблему. Два сильных предложения: 1) Научитесь использовать [VisualVM] (http://docs.oracle.com/javase/6/docs/technotes/guides/visualvm/) (или эквивалент), 2) Считать на [Устранение неисправностей памяти] (http://docs.oracle.com/javase/7/docs/webnotes/tsg/TSG-VM/html/memleaks.html) – FoggyDay

1

«очень большой файл» не означает, что ваша программа будет использовать очень большой объем памяти. Это, скорее всего, означает, что вы можете потратить немало времени на обработку файла, но на самом деле не так много общего с пространством, которое вы используете.

Только актуальная часть файла должна оставаться в памяти.

1

but quies know if this is solved by another way

Да, конечно, это еще один способ: когда сериализация вашего XML, не используйте StringWriter в качестве пункта назначения. Если вы хотите, чтобы ваш XML закончил работу в файле, создайте для него соответствующий FileWriter и передайте этот код вашему XML-сериализующему коду.

Если бы вы включили больше из stacktrace вашего исключения, я бы, возможно, смог дать вам более точный совет, чем указано выше. Ваш фактический код, создающий исключение, также помог бы.

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