2011-12-02 10 views
6

Pasé de String test += str; donde test creció exponencialmente grande con miles y miles de caracteres. Tardó 45 minutos en ejecutarse, probablemente creando cadenas grandes y eliminando basura. Luego escaloné la entrada como esta, lo que la llevó a 30 segundos.StringBuilder error de memoria al trabajar con cadenas grandes en java

Esta parece ser la forma barata de hacerlo, pero funcionó bien:

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 = ""; 
    } 

Entonces descubrí que existe StringBuilder, y he estado tratando de usarlo, ya que, la sustitución de todas las operaciones de cadena con él .

El problema es que sigo obteniendo un java.lang.OutOfMemoryError con un desbordamiento de pila de memoria Java. Creo que la cadena es demasiado larga para almacenarla en la memoria como un objeto StringBuilder, porque hace que aproximadamente 1/50th del progreso que mi código anterior hizo antes de fallar con un error de falta de memoria. Solo funciona con quizás menos de mil caracteres.

¿Por qué una cuerda puede contener toda la salida y esto no puede acercarse? Además, si añado texto al JTextPane, ¿cuánta memoria necesita? Si vuelco el contenido StringBuilder a JTextpane y sigo añadiendo y borrando StringBuilder que tampoco parece funcionar.

Aquí está el código existente. es sólo un objeto que se pasa página:

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); 
    } 
} 

Aquí está el error:

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) 

Creo que esto es lo que es un seguimiento de pila:

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

¿Cuáles son sus parámetros de VM? Intenta aumentar el tamaño del montón. – Viruzzo

+0

Podría agregar el código donde está utilizando la clase StringBuilder. El error es más probable que esté allí. – JustinKSU

+0

Más detalles ayudarían. Dudo que la cadena en la memoria te esté quedando sin memoria. ¿Tienes la stacktrace? –

Respuesta

5

Al parecer, su aplicación doen't tener suficiente memoria para completar la operación. Por lo tanto, debe especificar indicadores de memoria en su máquina virtual. Puede intentar lo siguiente:

java -Xms256m -Xmx512m YourApp 

Dónde:

  • Xms MINIMO memoria asignada por su programa en el arranque (en el MB ejemplo 256)
  • de memoria máximo -Xmx asignado por el programa si lo necesitan más (en el ejemplo 512 MB)
+1

Es una especie de solución de solución rápida que realmente no escala o explica cómo el uso de String vs StringBuilder realmente afecta el consumo de memoria. –

+2

No se considera una solución rápida: cuantos más datos desee conservar en la memoria, más memoria necesitará. – Puce

+0

Althoug StringBuilder puede necesitar un poco más de memoria que un solo objeto String ya que mantiene abiertos algunos espacios libres para nuevos datos. – Puce

3

Bueno, una de las cosas que podría suceder es el hecho de que en Java, java.lang.String recibe un trato especial. Las cadenas son inmutables y, por lo tanto, la JVM ubica cada objeto String en un grupo. La función de este grupo, entre otras, es el hecho de que se usa como una especie de "caché" donde si crea múltiples instancias String con el "texto" real valor idéntico, la misma instancia se reutilizará del grupo. De esta forma, la creación de lo que parece ser un gran número de instancias de objetos String con el mismo texto interno volverá a tener muy pocas instancias String reales en la memoria. Por otro lado, si usa el mismo texto para inicializar varias instancias de StringBuilder, esas serán instancias separadas (que contienen el mismo texto) y, por lo tanto, ocupará más memoria.

Por otro lado, la concatenación de cadenas (como String c = "a"+"b";), de hecho, crear más instancias de objetos que si lo haces con StribgBuilder (como new StringBuilder("a").append("b");).

+0

Ya veo. Entonces, ¿crees que esto es lo que podría estar causando el error de falta de memoria? No pensé que un solo objeto StringBuilder con menos de mil caracteres usaría tanta memoria. – montag

+0

Me acabo de dar cuenta de que probablemente tenga más de mil caracteres. – montag

+0

¿Se puede depurar con Eclipse para saber cuánto tiempo dura la cadena? – davidfrancis

Cuestiones relacionadas