Estoy escribiendo una aplicación Swing del lado del cliente (diseñador gráfico de fuentes) en Java 5 . Recientemente, me encuentro con un 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 investigación rápida, encontré Ergonomics en la máquina virtual Java 5.0 y otros que dicen en la máquina Windows que el JVM tiene el tamaño máximo de almacenamiento dinámico predeterminado 64MB
.
Dada esta situación, ¿cómo debo lidiar con esta restricción?
Podría aumentar el tamaño máximo de almacenamiento dinámico utilizando la opción de línea de comandos para Java, pero eso requeriría averiguar la RAM disponible y escribir algún programa o script de inicio. Además, aumentar a un máximo finito no elimina el problema en última instancia .
Podría reescribir parte de mi código para persistir 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 los detalles de las ideas anteriores o algunas alternativas como la memoria virtual automática, extender el tamaño del montón dinámicamente , sería genial.
fuente
Respuestas:
En última instancia, siempre tiene un máximo de almacenamiento dinámico finito para usar, sin importar en qué plataforma se esté ejecutando. En Windows de 32 bits, esto es alrededor
2GB
(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 (presumiblemente para que el programador no pueda crear programas que tengan una asignación de memoria desbocada sin encontrarse con este problema y tener que examinar exactamente lo que están haciendo).Por lo tanto, dado que existen varios enfoques que puede 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 de basura como Java o C # es mantener referencias a objetos que ya no está utilizando, o asignar muchos objetos cuando podría reutilizarlos . Mientras los objetos tengan una referencia a ellos, continuará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 se haga referencia a ellos, o 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 un 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 de almacenamiento dinámico cuando inicie el programa. Sin embargo, una vez que realice el perfil de la 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 (tal vez dependiendo del tamaño de entrada), siempre se encontrará con este problema. Solo después de agotar todo esto, tendrá que buscar objetos de almacenamiento en caché en el disco, etc. En este punto, debe 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 las técnicas como el almacenamiento en caché y el IO mapeado en memoria se vuelven útiles.
fuente
Ejecute Java con la opción de línea de comandos
-Xmx
, que establece el tamaño máximo del montón.Ver aquí para más detalles .
fuente
Puede especificar por proyecto cuánto espacio de almacenamiento dinámico desea su proyecto
Lo siguiente es para Eclipse Helios / Juno / Kepler :
Clic derecho del mouse en
luego agrega esto
fuente
Aumentar el tamaño del montón no es una "solución", es un "yeso", 100% temporal. Se bloqueará nuevamente en otro lugar. Para evitar estos problemas, escriba código de alto rendimiento.
fuente
Gran advertencia ---- en mi oficina, estábamos descubriendo que (en algunas máquinas con Windows) no podíamos asignar más de 512 m para el almacenamiento dinámico de Java. Esto se debió 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 otra manera, conducirá a otro error "Montón inicial demasiado pequeño").No tengo idea de si esto sucede con otros productos AV, pero presumiblemente esto está sucediendo porque el programa AV está reservando un pequeño bloque de memoria en cada espacio de direcciones, evitando así una sola asignación realmente grande.
fuente
Los argumentos de VM funcionaron para mí en eclipse. Si está utilizando eclipse versión 3.4, 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 hacerlo y
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.
fuente
Sí, con
-Xmx
usted puede configurar más memoria para su JVM. Para asegurarse de que no pierda ni pierda memoria. Realice un volcado de almacenamiento dinámico y use el Analizador de memoria Eclipse para analizar el consumo de memoria.fuente
Me gustaría agregar recomendaciones de solución de problemas de Oracle artículo .
Excepción en el hilo thread_name: java.lang.OutOfMemoryError: espacio de almacenamiento dinámico de Java
Posibles Causas:
Problema de configuración simple , donde el tamaño de almacenamiento dinámico especificado es insuficiente para la aplicación.
La aplicación contiene referencias involuntarias a objetos , y esto evita que los objetos se recojan basura.
Uso excesivo de finalizadores .
Después de la recolección de basura , los objetos se ponen en cola para su finalización , lo que ocurre más adelante. Los finalizadores son ejecutados por un hilo de daemon que da servicio a la cola de finalización. Si el subproceso finalizador no puede seguir el ritmo de la cola de finalización, entonces el montón de Java podría llenarse y se generaría 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 que es más rápida que la velocidad a la que el subproceso finalizador está atendiendo esa cola.
fuente
Siga los pasos a continuación:
Abierto
catalina.sh
desde tomcat / bin.Cambiar JAVA_OPTS a
Reinicia tu gato
fuente
Leí en otro lugar que puedes probar: catch java.lang.OutOfMemoryError y en el bloque catch, puedes liberar todos los recursos que sabes que pueden usar mucha memoria, cerrar conexiones, etc., y luego hacer un
System.gc()
luego volver a intentar lo que sea que ibas a hacerOtra forma es esta, aunque no sé si esto funcionaría, pero actualmente estoy probando si funcionará en mi aplicación.
La idea es hacer la recolección de basura llamando a System.gc () que se sabe que aumenta la memoria libre. Puede seguir verificando esto después de que se ejecute un código de memoria.
fuente
Una manera fácil de resolver
OutOfMemoryError
en Java es aumentar el tamaño máximo de almacenamiento dinámico utilizando las opciones de JVM-Xmx512M
almacenamiento , esto resolverá inmediatamente su OutOfMemoryError. Esta es mi solución preferida cuando obtengo OutOfMemoryError en Eclipse, Maven o ANT mientras construyo el proyecto porque, según el tamaño del proyecto, puede quedarse sin memoria fácilmente.Aquí hay un ejemplo de cómo aumentar el tamaño máximo de almacenamiento dinámico de JVM. También es mejor mantener la ración -Xmx a -Xms 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"
Link de referencia
fuente
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, 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)
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 /
2. Abra y escriba estos parámetros para configurar el modo preferible.
3)
service tomcat restart
fuente
Me he enfrentado al mismo problema con el tamaño del montón de Java.
Tengo dos soluciones si está utilizando Java 5 (1.5).
simplemente instale jdk1.6 y vaya a las preferencias de eclipse y configure la ruta jre de jav1 1.6 tal como la ha instalado.
Verifique su argumento 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á...
fuente
Si necesita controlar su uso de memoria en tiempo de ejecución, el
java.lang.management
paquete ofreceMBeans
que puede usarse para monitorear los grupos de memoria en su VM (por ejemplo, espacio edén, generación permanente, etc.), y también el comportamiento de recolección de basura.El espacio de almacenamiento dinámico libre reportado por estos MBeans variará enormemente dependiendo del comportamiento de GC, particularmente si su aplicación genera muchos objetos que luego se editan por GC. Un enfoque posible es monitorear el espacio de almacenamiento dinámico libre después de cada GC completo, que puede utilizar para tomar una decisión sobre la liberación de memoria mediante la persistencia de objetos.
En última instancia, su mejor opción es limitar su 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.
fuente
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, posible en Java 6u10 y posterior), ya que le permite especificar los diversos argumentos para la JVM en forma cruzada camino de plataforma.
De lo contrario, necesitará un iniciador específico del sistema operativo que establezca los argumentos que necesita.
fuente
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 la publicación Wildfly Heap Issue
fuente
Con respecto a los netbeans, puede establecer el tamaño máximo de almacenamiento dinámico 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' .
fuente
Si sigue asignando y manteniendo referencias a objetos, completará cualquier cantidad de memoria que tenga.
Una opción es cerrar y abrir un archivo transparente cuando cambian las pestañas (solo mantiene un puntero al archivo, y cuando el usuario cambia la pestaña, cierra y limpia todos los objetos ... hará que el archivo cambie más lentamente ... pero ...), y tal vez mantenga 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) cierra ese archivo, limpia sus objetos y advierte al usuario que debe cerrar sin usar archivos.
Su idea de ampliar 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 pistas que he visto con pérdidas de memoria es:
-> Recuerda que si pones algo en una colección y luego te olvidas de él, aún tienes una fuerte referencia, así que anula la colección, límpiala o haz algo con ella ... si no, encontrarás un pérdida de memoria difícil de encontrar.
-> Tal vez, el uso de colecciones con referencias débiles (débileshashmap ...) puede ayudar con problemas de memoria, pero debe tener cuidado con eso, ya que puede encontrar que el objeto que busca se ha recopilado.
-> Otra idea que he encontrado es desarrollar una colección persistente que se almacena en los objetos de la base de datos menos utilizados y cargados de forma transparente. Este sería probablemente el mejor enfoque ...
fuente
Si todo lo demás falla, además de aumentar el tamaño máximo de almacenamiento dinámico, intente también aumentar el tamaño de intercambio. Para Linux, a partir de ahora, las instrucciones relevantes se pueden encontrar en https://linuxize.com/post/create-a-linux-swap-file/ .
Esto puede ayudar, por ejemplo, compilando algo grande en una plataforma integrada.
fuente