2011-12-02 43 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

相關問題