Pregunta

Estoy escribiendo un lado del cliente Balancearse aplicación (diseñador de fuentes gráficas) en java 5.Recientemente, me estoy encontrando java.lang.OutOfMemoryError: Java heap space error 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é Ergonomía en la Máquina Virtual Java 5.0 y otros dicen que en la máquina Windows la JVM tiene por defecto el tamaño máximo de almacenamiento dinámico como 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 línea de comando opción para Java, pero eso requeriría averiguar la RAM disponible y escribir algún programa o script de inicio.Además, aumentando hasta cierto punto finito máximo no lo hace por último deshacerse del problema.

Podría reescribir parte de mi código para conservar objetos en el sistema de archivos con frecuencia (usar la base de datos es lo mismo) para liberar memoria.Podría funcionar, pero probablemente también sea mucho trabajo.

Si pudiera indicarme detalles de las ideas anteriores o algunas alternativas como memoria virtual automática, ampliando dinámicamente el tamaño del montón, eso será grandioso.

¿Fue útil?

Solución

En última instancia, siempre tienes un máximo finito de montón para usar sin importar en qué plataforma estés ejecutando.En Windows de 32 bits esto es aproximadamente 2GB (no específicamente montón, sino cantidad total de memoria por proceso).Simplemente sucede que Java elige hacer que el valor predeterminado sea más pequeño (presumiblemente para que el programador no pueda crear programas que tengan una asignación de memoria descontrolada sin encontrarse con este problema y tener que examinar exactamente lo que están haciendo).

Dado esto, existen varios enfoques que podría adoptar para determinar qué cantidad de memoria necesita o para reducir la cantidad de memoria que está utilizando.Un error común con los lenguajes de recolección de basura como Java o C# es mantener referencias a objetos que usted no más está utilizando o asignando muchos objetos cuando podría reutilizar ellos en su lugar.Mientras los objetos tengan una referencia a ellos, seguirán utilizando el espacio del montón ya que el recolector de basura no los eliminará.

En este caso, puede utilizar un perfilador 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 se haga referencia a ellos 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 algún motivo y necesita mantener referencias (dependiendo de lo que esté haciendo, este podría ser el caso), solo necesitará aumentar el tamaño máximo del montón cuando inicie el programa.Sin embargo, una vez que realice el perfil de memoria y comprenda cómo se asignan sus objetos, debería tener una mejor idea de cuánta memoria necesita.

En general, si no puede garantizar que su programa se ejecutará en una cantidad finita de memoria (quizás dependiendo del tamaño de la entrada), siempre se encontrará con este problema.Sólo después de agotar todo esto necesitarás buscar 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 de 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 técnicas como el almacenamiento en caché y la E/S asignada en memoria se vuelven útiles.

Otros consejos

Ejecute Java con la opción de línea de comandos -Xmx, que establece el máximo tamaño del montón.

Ver aquí para más detalles.

Podrías especificar por proyecto cuánto espacio de almacenamiento dinámico quiere su proyecto

Lo siguiente es para Eclipse Helios/Juno/Kepler:

Haga clic derecho en

 Run As - Run Configuration - Arguments - Vm Arguments, 

entonces agrega esto

-Xmx2048m

Aumentar el tamaño del montón no es una "solución", es un "yeso", 100% temporal.Volverá a estrellarse en algún otro lugar.Para evitar estos problemas, escriba código de alto rendimiento.

  1. Utilice variables locales siempre que sea posible.
  2. Asegúrate de seleccionar el objeto correcto (EJ.:Selección entre String, StringBuffer y StringBuilder)
  3. Utilice un buen sistema de código para su programa (EX:Usando variables estáticas VS variables no estáticas)
  4. Otras cosas que podrían funcionar en su código.
  5. Intenta moverte con múltiples ENhebramientos.

Gran advertencia: en mi oficina, descubrimos que (en algunas máquinas con Windows) no podíamos 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, descubrimos que podíamos asignar al menos 1,6 GB, es decir, -Xmx1600m (m es obligatorio, de lo contrario generará otro error "Montón inicial demasiado pequeño") funciona.

No tengo idea si esto sucede con otros productos AV, pero presumiblemente sucede porque el programa AV reserva un pequeño bloque de memoria en cada espacio de direcciones, evitando así una asignación única realmente grande.

Los argumentos de VM funcionaron para mí en eclipse.Si está utilizando eclipse versión 3.4, haga lo siguiente

ir a Run --> Run Configurations --> luego seleccione el proyecto en maven build --> luego seleccione la pestaña "JRE" --> luego ingrese -Xmx1024m.

Alternativamente podrías hacer Run --> Run Configurations --> select the "JRE" tab --> luego entra -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.Puedes optimizar la forma que quieras.

Si, con -Xmx puede configurar más memoria para su JVM.Para asegurarse de no perder ni desperdiciar memoria.Tome un volcado de montón y use el analizador de memoria de eclipse para analizar su consumo de memoria.

Me gustaría agregar recomendaciones de Oracle. solución de problemas artículo.

Excepción en el hilo thread_name: java.lang.OutOfMemoryError:Espacio de montón de Java

El mensaje detallado de espacio en el 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:

  1. Problema de configuración simple, donde el tamaño del montón especificado es insuficiente para la aplicación.

  2. La aplicación contiene involuntariamente referencias a objetos, y esto evita que los objetos sean recolectados como basura.

  3. Uso excesivo de finalizadores..

Otra posible fuente de este error surge con las aplicaciones que hacen un uso excesivo de finalizadores.Si una clase tiene un método de finalización, entonces los objetos de ese tipo no recuperan su espacio en el momento de la recolección de basura.

Después recolección de basura, los objetos están en cola para finalización, que ocurre más tarde. finalizadores son ejecutados por un hilo demonio que da servicio a la cola de finalización.Si el finalizador El hilo no puede seguir el ritmo de la cola de finalización, entonces el montón de Java podría llenarse y este tipo de Error de memoria insuficiente se lanzaría una excepción.

Un escenario que puede causar esta situación es cuando una aplicación crea hilos de alta prioridad eso causa el finalización la cola aumente a una velocidad que es más rápida que la velocidad a la que el subproceso finalizador presta servicio a esa cola.

Siga los pasos a continuación:

  1. Abierto catalina.sh de tomcat/bin.

  2. Cambie 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"
    
  3. Reinicia tu gato

Manera fácil de resolver OutOfMemoryError en Java es aumentar el tamaño máximo del montón mediante el uso de opciones de JVM -Xmx512M, esto resolverá inmediatamente 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.

A continuación se muestra un ejemplo de cómo aumentar el tamaño máximo del montón de JVM. Además, es mejor mantener la relación -Xmx a -Xms 1:1 o 1:1,5 si está configurando el tamaño del montón en su aplicación Java.

export JVM_ARGS="-Xms1024m -Xmx1024m"

Link de referencia

De forma predeterminada, para el desarrollo, JVM utiliza un tamaño y una configuración pequeños para otras funciones relacionadas con el rendimiento.Pero para la producción puedes sintonizar, por ejemplo.(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 ha alcanzado el tamaño máximo, se producirá un 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 la plataforma Linux para la configuración preferible del modo de producción.

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.cree 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 Java, las pilas de subprocesos y las manijas nativas se asignan en la memoria separadas del montón, así como las estructuras de datos internos JVM.

Me he enfrentado al mismo problema con el tamaño del montón de Java.

Tengo dos soluciones si estás usando Java 5 (1.5).

  1. simplemente instale jdk1.6 y vaya a las preferencias de eclipse y configure la ruta jre de jav1 1.6 tal como lo instaló.

  2. Verifique su argumento VM y déjelo ser 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á...

Leí en otro lugar que puedes probar: captura java.lang.OutOfMemoryError y en el bloque catch, puedes liberar todos los recursos que sabes que podrían usar mucha memoria, cerrar conexiones, etc., luego hacer una System.gc() luego vuelva a intentar lo que iba a hacer.

Otra forma es esta, aunque no sé si funcionaría, pero actualmente estoy probando si funcionará en mi aplicación.

La idea es realizar una recolección de basura llamando a System.gc(), que se sabe que aumenta la memoria libre.Puedes seguir comprobando esto después de que se ejecute un código que devora la memoria.

//Mimimum acceptable free memory you think your app needs
long minRunningMemory = (1024*1024);

Runtime runtime = Runtime.getRuntime();

if(runtime.freeMemory()<minRunningMemory)
 System.gc();

Si necesita monitorear el uso de su memoria en tiempo de ejecución, el java.lang.management ofertas de paquetes MBeans que se puede utilizar para monitorear los grupos de memoria en su VM (por ejemplo, Eden Space, generación permanente, etc.) y también el comportamiento de recolección de basura.

El espacio libre en el montón reportado por estos MBeans variará mucho dependiendo del comportamiento del GC, particularmente si su aplicación genera muchos objetos que luego se editan en GC.Un enfoque posible es monitorear el espacio libre en el montón después de cada GC completo, lo que es posible que pueda utilizar para tomar una decisión sobre la liberación de memoria mediante objetos persistentes.

En última instancia, lo mejor que puede hacer es limitar la retención de memoria tanto como sea posible mientras 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.

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 de red; es posible en Java 6u10 y posteriores), ya que le permite especificar los diversos argumentos para la JVM en una cruz. Camino de la plataforma.

De lo contrario, necesitará un iniciador específico del sistema operativo que establezca los argumentos que necesita.

Si este problema ocurre en Wildfly 8 y JDK1.8, entonces 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 Problema del montón de moscas salvajes

Con respecto a netbeans, puede establecer el tamaño máximo del montón para resolver el problema.

Vaya a 'Ejecutar', luego --> 'Establecer configuración del proyecto' --> 'Personalizar' --> 'ejecutar' de su ventana emergente --> 'Opción VM' --> complete '-Xms2048m -Xmx2048m' .

Si continúa asignando y manteniendo referencias al objeto, llenará cualquier cantidad de memoria que tenga.

Una opción es cerrar y abrir un archivo transparente cuando cambian de pestaña (solo mantiene 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 mantener sólo 3 o 4 archivos en la memoria.

Otra cosa que debe hacer es, cuando el usuario abre un archivo, cargarlo e interceptar cualquier OutOfMemoryError, luego (como no es posible abrir el archivo) cerrar ese archivo, limpiar sus objetos y advertir al usuario que debe cerrar los no utilizados. 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 sugerencias que he visto con pérdidas de memoria son:

--> Ten en cuenta que si pones algo en una colección y luego lo olvidas, todavía tienes una fuerte referencia a ello, así que anula la colección, límpiala o haz algo con ella...de lo contrario, será difícil encontrar una pérdida de memoria.

--> Tal vez, usar colecciones con referencias débiles (weakhashmap...) pueda ayudar con los problemas de memoria, pero debe Ten cuidado con ello, porque podrías encontrarte con que el objeto que buscas ha sido recogido.

-> Otra idea que encontré es desarrollar una colección persistente que almacene en la base de datos los objetos menos utilizados y cargados de forma transparente.Este sería probablemente el mejor enfoque...

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top