在java中使用大字符串时StringBuilder内存不足错误

我从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内存堆溢出的java.lang.OutOfMemoryError 。 我认为字符串太长而无法作为StringBuilder对象存储在内存中,因为它占据了我之前的代码在崩溃时出现内存不足错误的大约1/50的进度。 它只能使用不到一千个字符。

为什么一个字符串可以保存整个输出,这不能接近? 另外,如果我将文本附加到JTextPane ,那需要多少内存? 如果我将StringBuilder内容转储到JTextpane并继续追加并清除似乎不起作用的StringBuilder

这是现有的代码。 Page只是一个被传递的对象:

 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) 

显然你的应用程序没有足够的内存来完成操作。 因此,您需要为虚拟机指定内存标志。 您可以尝试以下方法:

  java -Xms256m -Xmx512m YourApp 

哪里:

  • 程序在启动时分配的Xms最小内存(在示例中为256 MB)
  • 如果需要更多,则程序分配的Xmx最大内存(在示例中为512 MB)

好吧,可能发生的一件事是,在Java中,java.lang.String得到特殊处理。 字符串是不可变的,因此JVM将每个String对象放在一个池中。此池的作用是用作一种“缓存”的事实,如果您创建具有实际“文本”的多个String实例值相同,将从池中重用相同的实例。 这样创建看起来像是大量具有相同文本的String对象实例的内容将实际上恢复为在内存中具有非常少的实际String实例。 另一方面,如果使用相同的文本初始化多个StringBuilder实例,那些实际上将是单独的实例(包含相同的文本),从而占用更多内存。

另一方面,连接字符串(例如String c = "a"+"b"; )实际上会创建更多的对象实例,如果你使用StribgBuilder(例如new StringBuilder("a").append("b"); )。