java.lang.OutOfMemoryError: se excedió el límite superior del GC

Recibo este error en un progtwig que crea varios (cientos de miles) objetos HashMap con unos pocos (15-20) entradas de texto cada uno. Estas cadenas deben recostackrse todas (sin dividirse en cantidades más pequeñas) antes de enviarlas a una base de datos.

Según Sun, el error ocurre “si se gasta demasiado tiempo en la recolección de basura: si más del 98% del tiempo total se gasta en recolección de basura y se recupera menos del 2% del montón, se lanzará OutOfMemoryError”. “.

Aparentemente, uno podría usar la línea de comando para pasar argumentos a la JVM para

  • Aumentando el tamaño del almacenamiento dynamic, a través de “-Xmx1024m” (o más), o
  • Desactivando la verificación de error por completo, a través de “-XX: -UseGCOverheadLimit”.

El primer enfoque funciona bien, el segundo termina en otro java.lang.OutOfMemoryError, esta vez sobre el montón.

Entonces, pregunta: ¿hay alguna alternativa programática a esto, para el caso de uso particular (es decir, varios pequeños objetos HashMap)? Si utilizo el método HashMap clear (), por ejemplo, el problema desaparece, pero también lo hacen los datos almacenados en HashMap. 🙂

El problema también se trata en un tema relacionado en StackOverflow.

En esencia, se está quedando sin memoria para ejecutar el proceso sin problemas. Opciones que te vienen a la mente:

  1. Especifique más memoria como la mencionó, intente con algo entre -como -Xmx512m primero
  2. Trabaje con lotes más pequeños de objetos HashMap para procesar a la vez si es posible
  3. Si tiene muchas cadenas duplicadas, use String.intern() en ellas antes de ponerlas en HashMap
  4. Utilice el constructor HashMap(int initialCapacity, float loadFactor) para sintonizar su caso

Lo siguiente funcionó para mí. Solo agrega el siguiente fragmento:

 dexOptions { javaMaxHeapSize "4g" } 

Para su build.gradle :

 android { compileSdkVersion 23 buildToolsVersion '23.0.1' defaultConfig { applicationId "yourpackage" minSdkVersion 14 targetSdkVersion 23 versionCode 1 versionName "1.0" multiDexEnabled true } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } packagingOptions { } dexOptions { javaMaxHeapSize "4g" } } 

@takrl: la configuración predeterminada para esta opción es:

 java -XX:+UseConcMarkSweepGC 

lo que significa que esta opción no está activa por defecto. Entonces, cuando dice que usó la opción ” +XX:UseConcMarkSweepGC “, asumo que estaba usando esta syntax:

 java -XX:+UseConcMarkSweepGC 

lo que significa que estabas activando explícitamente esta opción. Para obtener la syntax correcta y la configuración predeterminada de Java HotSpot VM Options @ este documento

Para el registro, tuvimos el mismo problema hoy. Lo arreglamos usando esta opción:

 -XX:-UseConcMarkSweepGC 

Aparentemente, esto modificó la estrategia utilizada para la recolección de basura, lo que hizo que el problema desapareciera.

Ummm … necesitarás:

  1. Repensa completamente tu algoritmo y estructuras de datos, de modo que no necesite todos estos pequeños HashMaps.

  2. Cree una fachada que le permita ubicar esos HashMaps dentro y fuera de la memoria según sea necesario. Un simple LRU-caché podría ser solo el ticket.

  3. Hasta la memoria disponible para la JVM. Si es necesario, incluso la compra de más RAM podría ser la solución más rápida y más barata si tiene la administración de la máquina que aloja a esta bestia. Una vez dicho esto, generalmente no soy partidario de las soluciones de “lanzar más hardware en eso”, especialmente si se puede diseñar una solución algorítmica alternativa dentro de un marco de tiempo razonable. Si sigue tirando más hardware a cada uno de estos problemas, pronto se encontrará con la ley de rendimientos decrecientes.

¿Qué intentas hacer de todos modos? Sospecho que hay un mejor enfoque para su problema real.

Utilice la implementación alternativa de HashMap ( Trove ). El Java HashMap estándar tiene una sobrecarga de memoria> 12x. Uno puede leer los detalles aquí .

No guarde toda la estructura en la memoria mientras espera llegar al final.

Escriba los resultados intermedios en una tabla temporal en la base de datos en lugar de hashmaps. Funcionalmente, una tabla de base de datos es equivalente a una hashmap, es decir, ambas admiten acceso con clave a los datos, pero la tabla no está enlazada a la memoria. los hasmaps

Si se hace correctamente, su algoritmo ni siquiera debe notar el cambio: correctamente, esto significa usar una clase para representar la tabla, incluso dándole un método put (clave, valor) y get (clave) como un hashmap.

Cuando la tabla intermedia esté completa, genere las declaraciones sql requeridas desde ella en lugar de desde la memoria.

El recostackdor paralelo arrojará un OutOfMemoryError si se OutOfMemoryError demasiado tiempo en la recolección de basura. En particular, si más del 98% del tiempo total se gasta en la recolección de basura y se recupera menos del 2% del montón, se OutOfMemoryError . Esta función está diseñada para evitar que las aplicaciones se ejecuten durante un período de tiempo prolongado sin apenas progreso porque el montón es demasiado pequeño. Si es necesario, esta función se puede desactivar agregando la opción -XX:-UseGCOverheadLimit a la línea de comando.

Si está creando cientos de miles de mapas hash, probablemente esté usando mucho más de lo que realmente necesita; a menos que trabaje con archivos o gráficos de gran tamaño, el almacenamiento de datos simples no debe desbordar el límite de memoria de Java.

Deberías intentar repensar tu algoritmo. En este caso, ofrecería más ayuda sobre ese tema, pero no puedo dar ninguna información hasta que proporcione más sobre el contexto del problema.

Si tiene java8 y puede usar el G1 Garbage Collector , ejecute su aplicación con:

  -XX:+UseG1GC -XX:+UseStringDeduplication 

Esto le dice al G1 que busque Cadenas similares y que solo conserve una de ellas en la memoria, y las otras solo son un puntero a esa Cadena en la memoria.

Esto es útil cuando tienes muchas cadenas repetidas. Esta solución puede funcionar o no y depende de cada aplicación.

Más información sobre:
https://blog.codecentric.de/en/2014/08/string-deduplication-new-feature-java-8-update-20-2/ http://java-performance.info/java-string-deduplication/

Repare las pérdidas de memoria en su aplicación con la ayuda de herramientas de perfil como eclipse MAT o VisualVM

Con JDK 1.7.x versiones posteriores, use G1GC , que gasta 10% en la recolección de basura a diferencia del 2% en otros algoritmos de GC.

Además de configurar la memoria del montón con -Xms1g -Xmx2g , intente `

 -XX:+UseG1GC -XX:G1HeapRegionSize=n, -XX:MaxGCPauseMillis=m, -XX:ParallelGCThreads=n, -XX:ConcGCThreads=n` 

Eche un vistazo al artículo de Oracle para ajustar estos parámetros.

Alguna pregunta relacionada con G1GC en SE:

Colección de basura y documentación de Java 7 (JDK 7) en G1

Colección de basura Java G1 en producción

Estrategia agresiva de recolectores de basura

En caso del error:

“Error interno del comstackdor: java.lang.OutOfMemoryError: Límite de sobrecarga del GC excedido en java.lang.AbstractStringBuilder”

aumente el espacio del montón de Java a 2 GB, es decir, -Xmx2g.

Necesita boost el tamaño de la memoria en Jdeveloper ir a setDomainEnv.cmd.

 set WLS_HOME=%WL_HOME%\server set XMS_SUN_64BIT=256 set XMS_SUN_32BIT=256 set XMX_SUN_64BIT=3072 set XMX_SUN_32BIT=3072 set XMS_JROCKIT_64BIT=256 set XMS_JROCKIT_32BIT=256 set XMX_JROCKIT_64BIT=1024 set XMX_JROCKIT_32BIT=1024 if "%JAVA_VENDOR%"=="Sun" ( set WLS_MEM_ARGS_64BIT=-Xms256m -Xmx512m set WLS_MEM_ARGS_32BIT=-Xms256m -Xmx512m ) else ( set WLS_MEM_ARGS_64BIT=-Xms512m -Xmx512m set WLS_MEM_ARGS_32BIT=-Xms512m -Xmx512m ) and set MEM_PERM_SIZE_64BIT=-XX:PermSize=256m set MEM_PERM_SIZE_32BIT=-XX:PermSize=256m if "%JAVA_USE_64BIT%"=="true" ( set MEM_PERM_SIZE=%MEM_PERM_SIZE_64BIT% ) else ( set MEM_PERM_SIZE=%MEM_PERM_SIZE_32BIT% ) set MEM_MAX_PERM_SIZE_64BIT=-XX:MaxPermSize=1024m set MEM_MAX_PERM_SIZE_32BIT=-XX:MaxPermSize=1024m 

Para este uso, utilice el código que se encuentra en el archivo gradle de la aplicación en Android de cierre.

dexOptions {javaMaxHeapSize “4g”}

Para mi caso, boost la memoria con la opción -Xmx fue la solución.

Tenía un archivo 10g leído en Java y cada vez que recibí el mismo error. Esto sucedió cuando el valor en la columna RES en el comando top alcanzó el valor establecido en la opción -Xmx. Luego, al boost la memoria con la opción -Xmx , todo salió bien.

Hubo otro punto también. Cuando establecí JAVA_OPTS o CATALINA_OPTS en mi cuenta de usuario y JAVA_OPTS la cantidad de memoria, obtuve el mismo error. Luego, imprimí el valor de esas variables de entorno en mi código, lo que me dio valores diferentes a los que establecí. La razón fue que Tomcat era la raíz de ese proceso y luego, como yo no era un su-doer, le pedí al administrador que boosta la memoria en catalina.sh en Tomcat.

Esto me ayudó a deshacerme de este error. Esta opción desactiva -XX: + DisableExplicitGC

    Intereting Posts