Ошибка StringBuilder в памяти при работе с большими строками в Java - PullRequest
6 голосов
/ 02 декабря 2011

Я вышел из String test += str;, где test выросло в геометрической прогрессии с тысячами и тысячами символов.Это заняло 45 минут, вероятно, от создания больших строк и удаления мусора.Затем я пошатнулся от ввода, как это, что довело его до 30 секунд.

Это похоже на дешевый способ сделать это, но он работал хорошо:

  if (secondDump.length() > 50)
  {
     intermedDump = intermedDump + secondDump;
     secondDump = "";
  }      

  if (intermedDump.length() > 100)
  {
     thirdDump = thirdDump + intermedDump;
     intermedDump = "";
  }
  if (thirdDump.length() > 500)
  {
     fourthDump = fourthDump + thirdDump;
     thirdDump = "";
  }
  if (fourthDump.length() > 1000)
  {
     fifthDump = fifthDump + fourthDump;
     fourthDump = "";
  }
  //with just this and not sixth.  Runtime>>>> : 77343
  if (fifthDump.length() > 5000)
  {
     sixthDump = sixthDump + fifthDump;
     fifthDump = "";
  }
  //with just this.  Runtime>>>> : 35903Runtime>>>> : 33780
  if (sixthDump.length() > 10000)
  {
     fillerDump = fillerDump + sixthDump;
     sixthDump = "";
  }

Затем я обнаружил, что StringBuilder существует, и с тех пор я пытался его использоватьзаменяя все строковые операции с ним.

Проблема в том, что я продолжаю получать java.lang.OutOfMemoryError с переполнением кучи памяти Java.Я думаю, что строка слишком длинная, чтобы хранить ее в памяти как объект StringBuilder, потому что она составляет около 1/50 от прогресса, достигнутого моим предыдущим кодом, до сбоя с ошибкой нехватки памяти.Он работает только с менее чем тысячей символов.

Почему строка может содержать весь вывод, и это не может приблизиться?Кроме того, если я добавлю текст к JTextPane, сколько памяти потребуется?Если я добавлю содержимое StringBuilder в JTextpane и продолжу добавлять и очищать StringBuilder, это тоже не сработает.

Вот существующий код.Страница - это просто передаваемый объект:

protected void concatPlates(page PageA) throws IOException
{
   if (backend.isFirstPage == false)
   {
      frontend.fillOutputPane("\n                                 " +
         "                                               \n", PageA);
      frontend.fillOutputPane("                                 " +
         "                                               \n", PageA);
      frontend.fillOutputPane("                                 " +
         "                                               \n", PageA);
   }
   for (int i = 0; i < PLATELEN-1; i++)
   {

      if (arrLeftCol[i].length() == 0)
      {
         /////////////////////////////////////////////////////////
         /////////////////////////////////////////////////////////
         frontend.fillOutputPane(arrLeftCol[i].append(
           arrRightCol[i]));
      }
     else
     {
        PageA.tempStrBuff = new StringBuilder(arrLeftCol[i].substring(0,40));
        frontend.fillOutputPane(PageA.tempStrBuff.append(arrRightCol[i]));
     }
     arrLeftCol[i].append("");
     arrRightCol[i].append("");

     backend.isFirstPage = false;
  }
}


//this is the frontend class
public static void fillOutputPane(String s, page PageA)
{
   fillOutputPane(PageA.getStrBuf());
}
public static void fillOutputPane(StringBuilder stringBuild)
{
  try
  {
     str.append(stringBuild);
  }
  catch (java.lang.OutOfMemoryError e)
  {
     System.out.println((str.length() * 16) /8);
     //System.out.println(str);
     System.out.println("out of memory error");
     System.exit(0);
  }
}

Вот ошибка:

Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Unknown Source)
at java.lang.AbstractStringBuilder.expandCapacity(Unknown Source)
at java.lang.AbstractStringBuilder.append(Unknown Source)
at java.lang.StringBuilder.append(Unknown Source)
at java.lang.StringBuilder.append(Unknown Source)
at backend.fill(backend.java:603)
at frontend$openL.actionPerformed(frontend.java:191)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.AbstractButton.doClick(Unknown Source)
at javax.swing.plaf.basic.BasicMenuItemUI.doClick(Unknown Source)
at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$000(Unknown Source)
at java.awt.EventQueue$1.run(Unknown Source)
at java.awt.EventQueue$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)

Я думаю, что это трассировка стека:

java.lang.Exception: Stack trace
at java.lang.Thread.dumpStack(Unknown Source)
at frontend.fillOutputPane(frontend.java:385)
at page.concatPlates(page.java:105)
at backend.setPlate(backend.java:77)
at backend.fill(backend.java:257)
at frontend$openL.actionPerformed(frontend.java:191)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.AbstractButton.doClick(Unknown Source)
at javax.swing.plaf.basic.BasicMenuItemUI.doClick(Unknown Source)
at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$000(Unknown Source)
at java.awt.EventQueue$1.run(Unknown Source)
at java.awt.EventQueue$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue$2.run(Unknown Source)
at java.awt.EventQueue$2.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)81240560
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)

Ответы [ 2 ]

5 голосов
/ 02 декабря 2011

Видимо, вашему приложению не хватает памяти для завершения операции.Поэтому вам нужно указать флаги памяти для вашей виртуальной машины.Вы можете попробовать следующее:

 java -Xms256m -Xmx512m YourApp

Где:

  • XMS минимальная память, выделенная вашей программой при запуске (в примере 256 МБ)
  • Xmx maximunпамять, выделенная вашей программой, если ей нужно больше (в примере 512 МБ)
3 голосов
/ 02 декабря 2011

Что может произойти, так это то, что в Java java.lang.String получает специальную обработку. Строки являются неизменяемыми, и, следовательно, JVM помещает каждый объект String в пул. Роль этого пула, помимо прочего, заключается в том, что он используется как своего рода «кэш», где при создании нескольких экземпляров String, имеющих фактический «текст» значение идентично, тот же экземпляр будет повторно использован из пула. Таким образом, создание большого количества экземпляров объекта String с одним и тем же текстом внутри приведет к тому, что в памяти будет очень мало реальных экземпляров String. С другой стороны, если вы используете один и тот же текст для инициализации нескольких экземпляров StringBuilder, они фактически будут отдельными экземплярами (содержащими один и тот же текст) и, следовательно, занимающими больше памяти.

С другой стороны, объединение строк (например, String c = "a"+"b";) фактически создаст больше экземпляров объектов, чем если вы сделаете это с StribgBuilder (например, new StringBuilder("a").append("b");).

...