solucion - Cómo lidiar con el error "java.lang.OutOfMemoryError: Java Heap Space"(64 MB de tamaño de pila)
java.lang.outofmemoryerror: java heap space r (18)
Estoy escribiendo una aplicación Swing del lado del cliente (diseñador gráfico de fuentes) en Java 5 . Recientemente, me estoy ejecutando en java.lang.OutOfMemoryError: Java heap space
error de java.lang.OutOfMemoryError: Java heap space
de almacenamiento en java.lang.OutOfMemoryError: Java heap space
porque no estoy siendo conservador en el uso de la memoria. El usuario puede abrir un número ilimitado de archivos, y el programa mantiene los objetos abiertos en la memoria. Después de una rápida investigación, encontré Ergonomics en la Máquina Virtual Java 5.0 y otros dicen que en la máquina Windows el tamaño de almacenamiento máximo predeterminado de JVM es de 64MB
.
Dada esta situación, ¿cómo debo lidiar con esta restricción?
Podría aumentar el tamaño máximo del montón usando la opción de línea de comandos para java, pero eso requeriría averiguar la RAM disponible y escribir algún programa de inicio o script. Además, aumentar a un máximo finito no elimina el problema en última instancia.
Podría volver a escribir parte de mi código para persistir los objetos en el sistema de archivos con frecuencia (usar la base de datos es lo mismo) para liberar la memoria. Podría funcionar, pero probablemente también sea mucho trabajo.
Si pudiera señalarme detalles de las ideas anteriores o algunas alternativas como la memoria virtual automática, ampliar dinámicamente el tamaño del montón , sería genial.
Aumentar el tamaño del montón no es un "arreglo", es un "yeso", 100% temporal. Se estrellará de nuevo en otro lugar. Para evitar estos problemas, escriba código de alto rendimiento.
- Use variables locales siempre que sea posible.
- Asegúrese de seleccionar el objeto correcto (EX: Selección entre String, StringBuffer y StringBuilder)
- Use un buen sistema de código para su programa (EX: Uso de variables estáticas VS variables no estáticas)
- Otras cosas que podrían funcionar en tu código.
- Intenta moverte con multy THREADING.
Con respecto a los netbeans, podría establecer el tamaño máximo del montón para resolver el problema. Primero, vaya a ''Ejecutar'', luego -> ''Configurar configuración del proyecto'' -> ''Personalizar'' -> ''ejecutar'' de su ventana emergente -> ''Opción de VM'' -> rellene ''-Xms2048m - Xmx2048m ''.
De forma predeterminada para el desarrollo, JVM utiliza un tamaño pequeño y una configuración pequeña para otras características relacionadas con el rendimiento. Pero para la producción puede ajustar (p. Ej., Además, puede existir una configuración específica del Servidor de aplicaciones) -> (Si todavía no hay suficiente memoria para satisfacer la solicitud y el montón ya alcanzó el tamaño máximo, se producirá un error OutOfMemoryError)
-Xms<size> set initial Java heap size
-Xmx<size> set maximum Java heap size
-Xss<size> set java thread stack size
-XX:ParallelGCThreads=8
-XX:+CMSClassUnloadingEnabled
-XX:InitiatingHeapOccupancyPercent=70
-XX:+UnlockDiagnosticVMOptions
-XX:+UseConcMarkSweepGC
-Xms512m
-Xmx8192m
-XX:MaxPermSize=256m (in java 8 optional)
Por ejemplo: en linux Platform para configuraciones de modo de producción preferibles.
Después de descargar y configurar el servidor de esta manera http://www.ehowstuff.com/how-to-install-and-setup-apache-tomcat-8-on-centos-7-1-rhel-7/
1.crear el archivo setenv.sh en la carpeta / opt / tomcat / bin /
touch /opt/tomcat/bin/setenv.sh
2. Abra y escriba estos parámetros para configurar el modo preferible.
nano /opt/tomcat/bin/setenv.sh
export CATALINA_OPTS="$CATALINA_OPTS -XX:ParallelGCThreads=8"
export CATALINA_OPTS="$CATALINA_OPTS -XX:+CMSClassUnloadingEnabled"
export CATALINA_OPTS="$CATALINA_OPTS -XX:InitiatingHeapOccupancyPercent=70"
export CATALINA_OPTS="$CATALINA_OPTS -XX:+UnlockDiagnosticVMOptions"
export CATALINA_OPTS="$CATALINA_OPTS -XX:+UseConcMarkSweepGC"
export CATALINA_OPTS="$CATALINA_OPTS -Xms512m"
export CATALINA_OPTS="$CATALINA_OPTS -Xmx8192m"
export CATALINA_OPTS="$CATALINA_OPTS -XX:MaxMetaspaceSize=256M"
3. service tomcat restart
Tenga en cuenta que la JVM utiliza más memoria que solo el montón. Por ejemplo, los métodos de Java, las pilas de hilos y los manejadores nativos se asignan en la memoria por separado del montón, así como las estructuras de datos internas de la JVM.
Ejecute Java con la opción de línea de comandos -Xmx
, que establece el tamaño máximo del montón.
El argumento de VM me funcionó en eclipse. Si está utilizando la versión 3.4 de Eclipse, haga lo siguiente
vaya a Run --> Run Configurations -->
luego seleccione el proyecto en maven build -> luego seleccione la pestaña "JRE" -> luego ingrese -Xmx1024m
.
Alternativamente, puede Run --> Run Configurations --> select the "JRE" tab -->
luego ingresar - Xmx1024m
Esto debería aumentar el montón de memoria para todas las compilaciones / proyectos. El tamaño de memoria anterior es de 1 GB. Puede optimizar la forma que desee.
En última instancia, siempre tiene un máximo finito de pila para usar, sin importar en qué plataforma esté ejecutando. En Windows de 32 bits, esto es alrededor de 2 gb (no específicamente el montón, sino la cantidad total de memoria por proceso). Simplemente sucede que Java elige hacer que el valor predeterminado sea más pequeño (probablemente para que el programador no pueda crear programas que tengan una asignación de memoria fuera de control sin encontrarse con este problema y tener que examinar exactamente lo que están haciendo).
Entonces, dado esto, hay varios enfoques que podría tomar para determinar qué cantidad de memoria necesita o para reducir la cantidad de memoria que está utilizando. Un error común con los lenguajes recolectados como Java o C # es mantener las referencias a objetos que ya no usa, o asignar muchos objetos cuando podría reutilizarlos. Mientras los objetos tengan una referencia a ellos, seguirán utilizando el espacio de almacenamiento dinámico, ya que el recolector de basura no los eliminará.
En este caso, puede usar un generador de perfiles de memoria Java para determinar qué métodos en su programa están asignando una gran cantidad de objetos y luego determinar si hay una manera de asegurarse de que ya no estén referenciados, o de no asignarlos en primer lugar. Una opción que he usado en el pasado es "JMP" http://www.khelekore.org/jmp/ .
Si determina que está asignando estos objetos por una razón y necesita mantenerse al margen de las referencias (según lo que esté haciendo, este podría ser el caso), solo tendrá que aumentar el tamaño máximo del montón cuando inicie el programa. Sin embargo, una vez que haga el perfil de la memoria y comprenda cómo se asignan sus objetos, debe tener una mejor idea de cuánta memoria necesita.
En general, si no puede garantizar que su programa se ejecutará en una cantidad limitada de memoria (quizás dependiendo del tamaño de la entrada), siempre se encontrará con este problema. Solo después de agotar todo esto, tendrá que buscar en el almacenamiento en caché de objetos en el disco, etc. En este punto, debería tener una muy buena razón para decir "Necesito Xgb de memoria" para algo y no puede solucionarlo mejorando Sus algoritmos o patrones de asignación de memoria. En general, este solo será el caso para los algoritmos que operan en grandes conjuntos de datos (como una base de datos o algún programa de análisis científico) y luego las técnicas como el almacenamiento en caché y la IO asignada a la memoria se vuelven útiles.
Gran advertencia ---- en mi oficina, nos encontramos con que (en algunas máquinas con Windows) no pudimos asignar más de 512 m para el montón de Java. Esto resultó ser debido al producto antivirus Kaspersky instalado en algunas de esas máquinas. Después de desinstalar ese producto AV, encontramos que podríamos asignar al menos 1.6gb, es decir, -Xmx1600m (m es obligatorio de otra manera, dará lugar a otro error que indica que el "montón inicial demasiado pequeño") funciona.
No tengo idea de si esto sucede con otros productos de AV, pero presumiblemente esto sucede porque el programa de AV está reservando un pequeño bloque de memoria en cada espacio de direcciones, lo que evita una asignación realmente grande.
La forma sencilla de resolver OutOfMemoryError
en java es aumentar el tamaño máximo de -Xmx512M
dinámico mediante el uso de las opciones JVM -Xmx512M
, esto resolverá de inmediato su OutOfMemoryError. Esta es mi solución preferida cuando obtengo OutOfMemoryError en Eclipse, Maven o ANT mientras construyo un proyecto porque, según el tamaño del proyecto, puedes quedarte sin memoria fácilmente.
Este es un ejemplo de cómo aumentar el tamaño máximo de almacenamiento dinámico de JVM. También es mejor mantener la proporción de -Xmx a -Xms ya sea 1: 1 o 1: 1.5 si está configurando el tamaño de almacenamiento dinámico en su aplicación java.
export JVM_ARGS="-Xms1024m -Xmx1024m"
Leí en otro lugar que puedes probar: captura java.lang.OutOfMemoryError y en el bloque catch, puedes liberar todos los recursos que sabes que pueden usar mucha memoria, cerrar conexiones, etc. Luego, haz un System.gc () y luego vuelve a intentar lo que ibas a hacer.
Otra forma es la siguiente, aunque no sé si funcionaría, pero actualmente estoy probando si funcionará en mi aplicación.
La idea es hacer una recolección de basura llamando a System.gc (), que se sabe que aumenta la memoria libre. Puede seguir comprobando esto después de que se ejecuta un código de engullimiento de memoria.
//Mimimum acceptable free memory you think your app needs
long minRunningMemory = (1024*1024);
Runtime runtime = Runtime.getRuntime();
if(runtime.freeMemory()<minRunningMemory)
System.gc();
Me gustaría agregar recomendaciones del artículo de solución de problemas de Oracle
Excepción en el hilo nombre_hilo: java.lang.OutOfMemoryError: espacio de almacenamiento dinámico de Java
El mensaje de detalle El espacio del montón de Java indica que el objeto no se pudo asignar en el montón de Java. Este error no implica necesariamente una pérdida de memoria.
Posibles causas:
Problema de configuración simple , donde el tamaño del montón especificado no es suficiente para la aplicación.
La aplicación sostiene involuntariamente referencias a objetos , y esto evita que los objetos se recojan.
Uso excesivo de los finalizadores .
Otra fuente potencial de este error surge con las aplicaciones que hacen un uso excesivo de los finalizadores. Si una clase tiene un método de finalización, entonces los objetos de ese tipo no tienen su espacio reclamado en el momento de la recolección de basura
Después de la recolección de basura , los objetos se ponen en cola para su finalización , lo que ocurre más tarde. los finalizadores se ejecutan mediante un subproceso daemon que da servicio a la cola de finalización. Si el subproceso finalizador no puede mantenerse al día con la cola de finalización, entonces el montón de Java podría llenarse y se lanzará este tipo de excepción OutOfMemoryError .
Un escenario que puede causar esta situación es cuando una aplicación crea subprocesos de alta prioridad que hacen que la cola de finalización aumente a una velocidad más rápida que la que el subproceso finalizador está atendiendo esa cola.
Me he enfrentado con el mismo problema de java tamaño de pila. Tengo dos soluciones si estás utilizando Java 5 (1.5).
Primero: -solo instale jdk1.6 y vaya a las preferencias de eclipse y establezca la ruta jre de jav1 1.6 como ha instalado.
2º: -Compruebe su argumento de VM y deje que sea lo que sea. simplemente agregue una línea debajo de todos los argumentos presentes en los argumentos de VM como -Xms512m -Xmx512m -XX: MaxPermSize = ... m (192m).
Creo que funcionará...
Puede especificar por proyecto cuánto espacio de almacenamiento desea su proyecto
Lo siguiente es para Eclipse Helios / Juno / Kepler :
Clic derecho del mouse sobre
Run As - Run Configuration - Arguments - Vm Arguments,
entonces agrega esto
-Xmx2048m
Sí, con -Xmx puede configurar más memoria para su JVM. Para estar seguro de que no se pierde ni se pierde la memoria. Tome un volcado de almacenamiento dinámico y use el analizador de memoria Eclipse para analizar el consumo de memoria.
Si continúa asignando y manteniendo referencias a objetos, llenará cualquier cantidad de memoria que tenga.
Una opción es cerrar y abrir un archivo transparente cuando cambian de pestaña (solo mantienes un puntero al archivo, y cuando el usuario cambia de pestaña, cierra y limpia todos los objetos ... hará que el archivo cambie más lento) ... pero ...), y tal vez tenga solo 3 o 4 archivos en la memoria.
Otra cosa que debe hacer es, cuando el usuario abre un archivo, lo carga e intercepta cualquier OutOfMemoryError, luego (ya que no es posible abrir el archivo) cierre ese archivo, limpie sus objetos y advierta al usuario que debe cerrar sin usar archivos.
Su idea de extender dinámicamente la memoria virtual no resuelve el problema, ya que la máquina tiene recursos limitados, por lo que debe tener cuidado y manejar los problemas de memoria (o al menos, tener cuidado con ellos).
Un par de consejos que he visto con fugas de memoria es:
-> Tenga en cuenta que si coloca algo en una colección y luego se olvida de él, todavía tiene una fuerte referencia a él, así que anule la colección, límpiela o haga algo con ella ... si no, encontrará un Fuga de memoria difícil de encontrar.
-> Tal vez, el uso de colecciones con referencias débiles (weakhashmap ...) puede ayudar con los problemas de memoria, pero debe tener cuidado con esto, ya que puede encontrar que el objeto que busca ha sido recolectado.
-> Otra idea que he encontrado es desarrollar una colección persistente que se almacene en los objetos de la base de datos menos utilizados y cargados de forma transparente. Este sería probablemente el mejor enfoque ...
Si este problema ocurre en Wildfly 8 y JDK1.8, debemos especificar la configuración de MaxMetaSpace en lugar de la configuración de PermGen.
Por ejemplo, necesitamos agregar la siguiente configuración en el archivo setenv.sh de wildfly. JAVA_OPTS="$JAVA_OPTS -XX:MaxMetaspaceSize=256M"
Para obtener más información, consulte Wildfly Heap Issue
Si necesita monitorear su uso de memoria en tiempo de ejecución, el paquete java.lang.management ofrece MBeans que se pueden usar para monitorear los grupos de memoria en su VM (por ejemplo, espacio eden, generación permanente, etc.) y también el comportamiento de recolección de basura.
El espacio de almacenamiento dinámico informado por estos MBeans variará enormemente dependiendo del comportamiento del GC, especialmente si su aplicación genera muchos objetos que luego serán creados por GC. Un posible enfoque es monitorear el espacio de almacenamiento dinámico libre después de cada GC completo, que puede utilizar para tomar una decisión sobre liberar memoria mediante la persistencia de objetos.
En última instancia, su mejor opción es limitar la retención de memoria en la medida de lo posible, mientras que el rendimiento sigue siendo aceptable. Como se señaló en un comentario anterior, la memoria siempre es limitada, pero su aplicación debe tener una estrategia para lidiar con el agotamiento de la memoria.
Siga los siguientes pasos:
Abra catalina.sh desde tomcat / bin.
Chnage JAVA_OPTS a
JAVA_OPTS="-Djava.awt.headless=true -Dfile.encoding=UTF-8 -server -Xms1536m -Xmx1536m -XX:NewSize=256m -XX:MaxNewSize=256m -XX:PermSize=256m -XX:MaxPermSize=256m -XX:+DisableExplicitGC"
Reinicia tu gato
Tenga en cuenta que si necesita esto en una situación de implementación, considere usar Java WebStart (con una versión "ondisk", no la red, es posible en Java 6u10 y posteriores), ya que le permite especificar los diversos argumentos a la JVM en una cruz. forma de plataforma.
De lo contrario, necesitará un lanzador específico del sistema operativo que establezca los argumentos que necesita.