java.lang.OutOfMemoryError: límite de sobrecarga del GC excedido
hashmap heap (16)
@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 dices que +XX:UseConcMarkSweepGC
la opción " +XX:UseConcMarkSweepGC
", asumo que estabas usando esta sintaxis:
java -XX:+UseConcMarkSweepGC
lo que significa que estaba activando explícitamente esta opción. Para obtener la sintaxis correcta y la configuración predeterminada de las opciones de Java HotSpot VM Options
@ este document
Recibo este error en un programa que crea varios objetos HashMap (cientos de miles) con unas pocas (15-20) entradas de texto cada una. Todas estas cadenas deben recopilarse (sin dividirse en cantidades más pequeñas) antes de enviarlas a una base de datos.
Según Sun, el error ocurre "si se pasa demasiado tiempo en la recolección de basura: si se pasa más del 98% del tiempo total en la recolección de basura y se recupera menos del 2% del montón, se lanzará un error OutOfMemory. ".
Aparentemente, uno podría usar la línea de comando para pasar argumentos a la JVM para
- Aumentar el tamaño del montón, a través de "-Xmx1024m" (o más), o
- Deshabilitando la comprobación de errores 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, pregunte: ¿hay alguna alternativa programática a esto, para el caso de uso particular (es decir, varios objetos HashMap pequeños)? Si uso el método HashMap clear (), por ejemplo, el problema desaparece, pero también lo hacen los datos almacenados en el HashMap. :-)
El problema también se trata en un tema relacionado en StackOverflow.
El colector paralelo lanzará un OutOfMemoryError
si se está gastando 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 característica está diseñada para evitar que las aplicaciones se ejecuten durante un período prolongado de tiempo mientras se avanza poco o nada 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.
En caso de error:
"Error interno del compilador: java.lang.OutOfMemoryError: límite de sobrecarga del GC excedido en java.lang.AbstractStringBuilder"
aumentar el espacio de -Xmx2g.
dinámico de java a 2 GB, es decir, -Xmx2g.
Esencialmente se está quedando sin memoria para ejecutar el proceso sin problemas. Opciones que vienen a la mente:
- Especifique más memoria como mencionó, intente algo intermedio como
-Xmx512m
primero - Trabaje con lotes más pequeños de objetos
HashMap
para procesar a la vez si es posible - Si tienes muchas cadenas duplicadas, usa
String.intern()
en ellas antes de ponerlas en elHashMap
- Utilice el constructor
HashMap(int initialCapacity, float loadFactor)
para ajustar su caso
Esto me ayudó a deshacerme de este error. Esta opción deshabilita -XX: + DisableExplicitGC
Lo siguiente funcionó para mí. Solo agrega el siguiente fragmento de código:
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"
}
}
Necesita aumentar el tamaño de la memoria en Jdeveloper y vaya 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
No almacene toda la estructura en la memoria mientras espera llegar al final.
Escriba resultados intermedios en una tabla temporal en la base de datos en lugar de mapas de hash: funcionalmente, una tabla de base de datos es el equivalente de un mapa hash, es decir, ambos admiten el acceso con clave a los datos, pero la tabla no está vinculada a la memoria, así que use una tabla indexada aquí en lugar de Los hashmaps.
Si se realiza correctamente, su algoritmo ni siquiera debería notar el cambio; aquí, correctamente, significa usar una clase para representar la tabla, incluso dándole un método de poner (clave, valor) y un método de obtener (clave) como un mapa hash.
Cuando la tabla intermedia esté completa, genere la (s) declaración (es) de SQL requerida desde ella en lugar de desde la memoria.
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.
Para este uso, utilice el código a continuación en el archivo de su aplicación gradle bajo el cierre de Android.
dexOptions {javaMaxHeapSize "4g"}
Para mi caso, aumentar la memoria usando la opción -Xmx
fue la solución.
Tuve un archivo de 10g leído en java y cada vez 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 aumentar la memoria con la opción -Xmx
, todo fue bien.
Había otro punto también. Cuando configuré JAVA_OPTS
o CATALINA_OPTS
en mi cuenta de usuario y JAVA_OPTS
la cantidad de memoria nuevamente, obtuve el mismo error. Luego, imprimí el valor de esas variables de entorno en mi código que me dio valores diferentes a los que establecí. La razón fue que Tomcat fue la raíz de ese proceso y luego, como no era un suplente, le pedí al administrador que aumentara la memoria en catalina.sh
en Tomcat.
Repare las fugas 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 el 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.
Algunas preguntas relacionadas con G1GC en SE:
Recolección de basura Java 7 (JDK 7) y documentación sobre G1
Si está creando cientos de miles de mapas hash, probablemente esté usando mucho más de lo que realmente necesita; a menos que esté trabajando con archivos o gráficos grandes, el almacenamiento de datos simples no debe desbordar el límite de memoria de Java.
Debes intentar y repensar tu algoritmo. En este caso, ofrecería más ayuda sobre ese tema, pero no puedo proporcionar ninguna información hasta que usted proporcione más información sobre el contexto del problema.
Si tiene java8 y puede usar el recolector de basura G1 , ejecute su aplicación con:
-XX:+UseG1GC -XX:+UseStringDeduplication
Esto le indica al G1 que encuentre cadenas similares y mantenga solo una de ellas en la memoria, y las otras son solo un indicador de esa cadena en la memoria.
Esto es útil cuando tienes muchas cadenas repetidas. Esta solución puede o no funcionar 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/
Ummm ... tendrás que:
Reconsidere completamente su algoritmo y estructuras de datos, de modo que no necesite todos estos pequeños HashMaps.
Cree una fachada que le permita ubicar esos HashMaps dentro y fuera de la memoria según sea necesario. Un simple LRU-cache podría ser solo el ticket.
Hasta la memoria disponible para la JVM. Si es necesario, incluso la compra de más RAM puede ser la solución más rápida y barata, si tiene la administración de la máquina que aloja a esta bestia. Dicho esto: generalmente no soy un fanático de las soluciones de "lanzar más hardware", especialmente si se puede pensar en una solución algorítmica alternativa dentro de un plazo razonable. Si continúa lanzando más hardware a cada uno de estos problemas, pronto se encontrará con la ley de rendimientos decrecientes.
¿Qué estás tratando de hacer de todos modos? Sospecho que hay un mejor enfoque para su problema real.