2011-12-02 127 views
6

我从String test += str;中去除了test,成千上万个字符以指数级增长。花了45分钟才能运行,可能是因为创建了大字符串并删除了垃圾。然后,我将这个输入错开了30秒。StringBuilder在使用java中的大字符串时出现内存不足错误

这似乎是便宜的方式做到这一点,但它运作良好:

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内存堆溢出。我认为这个字符串太长了,无法存储在内存中,因为它使得我之前的代码在内存不足错误崩溃之前所做的大约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) 
+1

什么是虚拟机参数?尝试增加堆大小。 – Viruzzo

+0

您可以在您使用StringBuilder类的地方添加代码。错误更可能在那里。 – JustinKSU

+0

更多细节将有所帮助。我怀疑内存中的字符串会导致内存不足。你有堆栈跟踪吗? –

回答

5

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

java -Xms256m -Xmx512m YourApp 

其中:

  • X毫秒minimun在启动你的程序分配的内存(例如256 MB)
  • XMX maximun存储你的程序分配的,如果它需要更多(在本例中为512 MB)
+1

这是一种快速修复的解决方案,并没有真正扩展或解释如何使用String vs StringBuilder实际影响内存消耗。 –

+2

这不被认为是一个快速修复 - 您想要保留在内存中的数据越多,需要的内存就越多。 – Puce

+0

Althoug StringBuilder可能需要比单个String对象更多的内存,因为它为新数据保持打开一些空闲插槽。 – Puce

3

那么可能发生的一件事情是,在Java中,java.lang.String得到了特殊的处理。字符串是不可变的,因此JVM将每个String对象放置在一个池中。这个池的作用之一就是用作一种“缓存”的事实,如果你创建了多个具有实际“文本”的String实例,值相同,相同的实例将从池中重用。通过这种方式创建好似大量String对象实例的内部相同的文本将事实上恢复为内存中实际的String实例很少。另一方面,如果使用相同的文本初始化多个StringBuilder实例,那么实际上它们将是单独的实例(包含相同的文本),因此会占用更多的内存。

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

+0

我明白了。那么你认为这可能是导致内存不足错误的原因吗?我不认为一个字符数不到一千个的StringBuilder对象会使用那么多的内存。 – montag

+0

我刚刚意识到它可能超过一千个字符。 – montag

+0

你可以使用Eclipse进行调试以查明字符串有多长? – davidfrancis

相关问题