xmx usage how check calculate java linux memory jvm heap

usage - Java se niega a iniciar: no se pudo reservar suficiente espacio para el montón de objetos



monitoring heap java (15)

Fondo

Tenemos un grupo de aproximadamente 20 blades linux. Algunos están ejecutando Suse, algunos están ejecutando Redhat. TODOS comparten el espacio NAS que contiene las siguientes 3 carpetas:

  • / NAS / app / java: un enlace simbólico que apunta a una instalación de Java JDK. Actualmente la versión 1.5.0_10
  • / NAS / app / lib: un enlace simbólico que apunta a una versión de nuestra aplicación.
  • / NAS / data - directorio donde se escribe nuestro resultado

Todas nuestras máquinas tienen 2 procesadores (hyperthreaded) con 4 gb de memoria física y 4 gb de espacio de intercambio. Limitamos el número de "trabajos" que cada máquina puede procesar en un momento dado a 6 (es probable que este número tenga que cambiar, pero eso no entra en el problema actual, así que ignórelo por el momento).

Algunos de nuestros trabajos establecen un tamaño Max Heap de 512 mb, otros reservan un tamaño de Heap Max de 2048 mb. Nuevamente, nos damos cuenta de que podríamos revisar nuestra memoria disponible si comenzamos 6 trabajos en la misma máquina con el tamaño de almacenamiento dinámico configurado en 2048, pero hasta donde sabemos esto aún no ha ocurrido.

El problema

De vez en cuando, un Trabajo fallará inmediatamente con el siguiente mensaje:

Error occurred during initialization of VM Could not reserve enough space for object heap Could not create the Java virtual machine.

Solíamos atribuir esto a demasiados trabajos que se ejecutaban al mismo tiempo en la misma máquina. El problema sucedió con la suficiente frecuencia ( QUIZÁ una vez al mes) que simplemente lo reiniciaríamos y todo estaría bien.

El problema recientemente empeoró. Todos nuestros trabajos que solicitan un tamaño máximo de almacenamiento dinámico de 2048m fallan inmediatamente casi todas las veces y deben reiniciarse varias veces antes de completarse.

Hemos ido a máquinas individuales e intentado ejecutarlas manualmente con el mismo resultado.

Depuración

Resulta que el problema solo existe para nuestras cajas SuSE. La razón por la que ha estado sucediendo con más frecuencia es porque hemos estado agregando más máquinas, y las nuevas son SuSE.

''cat / proc / version'' en los cuadros de SuSE nos da:

Linux version 2.6.5-7.244-bigsmp (geeko@buildhost) (gcc version 3.3.3 (SuSE Linux)) #1 SMP Mon Dec 12 18:32:25 UTC 2005

''cat / proc / version'' en los cuadros RedHat nos dan:

Linux version 2.4.21-32.0.1.ELsmp ([email protected]) (gcc version 3.2.3 20030502 (Red Hat Linux 3.2.3-52)) #1 SMP Tue May 17 17:52:23 EDT 2005

''uname -a'' nos da lo siguiente en AMBOS tipos de máquinas:

UTC 2005 i686 i686 i386 GNU/Linux

No se están ejecutando trabajos en la máquina, y ningún otro proceso está utilizando mucha memoria. Todos los procesos actualmente en ejecución podrían estar usando un total de 100 MB.

''top'' actualmente muestra lo siguiente:

Mem: 4146528k total, 3536360k used, 610168k free, 132136k buffers Swap: 4194288k total, 0k used, 4194288k free, 3283908k cached

''vmstat'' actualmente muestra lo siguiente:

procs -----------memory---------- ---swap-- -----io---- --system-- ----cpu---- r b swpd free buff cache si so bi bo in cs us sy id wa 0 0 0 610292 132136 3283908 0 0 0 2 26 15 0 0 100 0

Si iniciamos un trabajo con la siguiente línea de comando (Max Heap de 1850 mb) comienza bien:

java/bin/java -Xmx1850M -cp helloworld.jar HelloWorld Hello World

Si aumentamos el tamaño máximo de almacenamiento dinámico a 1875 mb, falla:

java/bin/java -Xmx1875M -cp helloworld.jar HelloWorld Error occurred during initialization of VM Could not reserve enough space for object heap Could not create the Java virtual machine.

Está bastante claro que la memoria que se está utilizando actualmente es para almacenamiento en memoria intermedia / almacenamiento en caché y es por eso que tan poco se muestra como ''gratis''. Lo que no está claro es por qué hay una línea mágica de 1850mb donde algo más alto significa que Java no puede comenzar.

Cualquier explicación sería muy apreciada.


¿El tamaño máximo de la memoria ulimit y la memoria virtual están configurados como ilimitados?


¿Qué es la JVM utilizada? Sé que BEA JRockit no supera los 1850 mB para el tamaño máximo de almacenamiento dinámico. No falla, pero advierte al usuario que no usará más de 1850 mB.

No sé por qué existe tal límite, pero sé que existe para BEA JRockit.

Atentamente.


Actualicé la memoria de una máquina de 2 GB a 4 GB y comencé a obtener el error inmediatamente:

$ java -version Error occurred during initialization of VM Could not reserve enough space for object heap Could not create the Java virtual machine.

El problema era el ulimit, que había establecido en 1 GB para el espacio direccionable. Aumentarlo a 2GB resolvió el problema.

-Xms y -Xmx no tuvieron ningún efecto.

Parece que java intenta obtener memoria en proporción a la memoria disponible, y falla si no puede.


Como se sugiere en otras respuestas, el problema se debe al agotamiento del espacio de direcciones virtuales. Un programa de espacio de usuario de 32 bits en Linux está generalmente limitado a 3 GB de AS; el kernel usa el 1GB restante (justificación: dado que el 1 GB superior es un mapeo fijo del kernel, no es necesario tocar la tabla de la página cuando se sirven las llamadas a los sistemas).

Los núcleos RHEL, sin embargo, implementan la llamada división de 4GB / 4GB donde el AS de 4GB completo está disponible para los procesos del espacio de usuario al costo de una ligera sobrecarga de tiempo de ejecución (el kernel vive en un AS virtual de 4GB separado)


Dado que ninguna de las otras sugerencias ha funcionado (incluidas muchas cosas que me hubiera sugerido a mí mismo), para ayudar a solucionar más problemas, ¿podría intentar ejecutar:

sysctl -a

¿En las máquinas SuSE y RedHat para ver si hay alguna diferencia? Supongo que las configuraciones predeterminadas son diferentes entre estas dos distribuciones que están causando esto.


Ejecutar un sistema operativo de 32 bits es un error; definitivamente deberías actualizar lo más pronto posible.

No sé si Java requiere que su montón esté en un solo bloque contiguo, pero si lo hace, pedir 1.8G de montón en un cuadro de 32 bits suena como un pedido difícil. Está asumiendo que hay un espacio de direcciones, casi la mitad, libre en el momento de inicio de JVM.

Dependiendo de qué otras bibliotecas se carguen en ese momento, puede que no exista. Las bibliotecas pueden asignar memoria donde quieran, por lo que podría fragmentar su espacio de direcciones lo suficiente como para que 1.8G no esté disponible en un solo bloque.

De todos modos, solo hay espacio de direcciones 3G máximo disponible en Linux de 32 bits. Las bibliotecas y la propia JVM usan algunas para empezar.


En Windows, resolví este problema editando directamente el archivo /bin/cassandra.bat, cambiando el valor de los parámetros JVM_OPTS "Xms" y "Xmx". Puede intentar editar el archivo / bin / cassandra. En este archivo veo una variable comentada JVM_OPTS, intento descomentar y editarla.


Escribí dos aplicaciones, una de tamaño mediano, y la otra, bastante pequeña. Arrancaría el de tamaño mediano (en linux, centos), sin argumentos (servidor de Java), y funcionaría perfectamente. Pero cuando encendí la aplicación más pequeña con "cliente de Java", me decía que no podía reservar suficiente espacio y que no se ejecutaría. Experimenté, y usé -Xms y -Xmx ambos con 10m, y ambos funcionarían sin quejarse ... ¡A la figura!


Estás usando un sistema operativo de 32 bits, por lo que vas a ver límites en el tamaño total debido a eso. Otras respuestas han cubierto esto con más detalle, así que evitaré repetir su información.

Un comportamiento que noté recientemente en nuestros servidores es que especificar un tamaño máximo de -Xmx dinámico con -Xmx sin especificar un tamaño de -Xms dinámico mínimo con -Xms llevaría a que la VM del servidor de Java intente de inmediato asignar toda la memoria necesaria para el tamaño de almacenamiento dinámico máximo. Y claro, si la aplicación alcanza ese tamaño de almacenamiento dinámico, esa es la cantidad de memoria que necesitará. Pero lo más probable es que sus aplicaciones comiencen con montones comparativamente pequeños y requieran un montón más grande en algún momento posterior. Además, al especificar el tamaño de almacenamiento dinámico mínimo, podrá comenzar el inicio de su aplicación con un montón más pequeño y crecer gradualmente ese montón.

Todo esto no te ayudará a aumentar tu tamaño máximo de almacenamiento dinámico, pero pensé que podría ser útil, así que ...


Esto tal vez fuera de la pista, pero hay dos cosas que vienen a la mente. Los dos siguientes suponen que está ejecutando una versión de 32 bits de Linux.

Hay un límite de tamaño de proceso en Linux, parece recordar que en CentOS era de alrededor de 2.5 gb y está configurado en el kernel (es decir, un recomple para cambiar). Su proceso podría estar golpeando eso una vez que sume todo el código de JVM + espacio de Permgen y el resto de las bibliotecas de JVM.

Lo segundo es algo con lo que me he enterado de que te estás quedando sin espacio de direcciones, suena raro, lo sé. Tuve un problema al ejecutar Glassfish con un montón de 1.5Gb, cuando intentó cumplir un JSP mi forking javac fracasaría porque el sistema operativo no podía asignar suficiente espacio de direcciones para el proceso recién creado a pesar de que había 12 gb de memoria en la caja. Puede haber algo similar pasando aquí.

Me temo que las únicas soluciones para los dos anteriores son actualizar a un kernel de 64 bits.

Espero que esto sirva para algo.


Estoy usando SOA env, Xmx reducido de 1024 a 768 en setSOADomainENV.cmd resolvió el problema.

REM set DEFAULT_MEM_ARGS=-Xms512m -Xmx1024m set DEFAULT_MEM_ARGS=-Xms512m -Xmx768m


Necesita ver la actualización de su sistema operativo y Java. Java 5.0 es EOL, pero si no puede actualizar a Java 6, ¡puede usar el último nivel de parche 22!

Windows de 32 bits está limitado a ~ 1.3 GB, por lo que está haciendo bien para ver el máximo en 1.8. Nota: este es un problema con la memoria continua, y mientras su sistema ejecuta su memoria, el espacio puede fragmentarse, por lo que no me sorprende que tenga este problema.

Un sistema operativo de 64 bits no tiene este problema, ya que tiene mucho más espacio virtual, ni siquiera tiene que actualizar a una versión de java de 64 bits para aprovechar esto.

Por cierto, en mi experiencia, Java 5.0 de 32 bits puede ser más rápido que Java 5.0 de 64 bits. No fue hasta muchos años después que la actualización 10 de Java 6 fue más rápida para 64 bits.


Parece que para los servidores de 32 bits hay una limitación de JVM que no se puede superar (a menos que encuentre una JVM especial de 32 bits que no imponga un límite de 2 GB o menos).

Este hilo en The Server Side tiene más detalles, incluidas varias personas que probaron varias JVM en arquitecturas de 32 bits. La JVM de IBM parece permitir 100 MB más, pero eso realmente no le dará lo que quiere.

http://www.theserverside.com/discussions/thread.tss?thread_id=26347

La solución "real" es usar un servidor de 64 bits con una JVM de 64 bits para obtener montones de más de 2 GB por proceso. Sin embargo, también es importante considerar el impacto de aumentar el tamaño de su dirección (no solo el espacio direccionable) mediante el uso de una JVM de 64 bits. Es probable que haya un impacto en el rendimiento y la memoria para procesar con menos de 4 GB de memoria.

Pensamiento: ¿cada uno de estos trabajos realmente requiere 2GB de memoria? ¿Hay alguna manera de modificar los trabajos para que se ejecuten dentro de 1,8 GB, por lo que este límite no es un problema?


Pasos a ejecutar ... para resolver el error producido durante la inicialización de la VM. No se pudo reservar suficiente espacio para el montón de objetos. No se pudo crear la máquina virtual Java.

Paso 1: reduce la memoria que antes usabas ... java -Xms128m -Xmx512m -cp simple.jar

paso 2: retire la RAM de la placa madre en algún momento y conéctela y reiníciela * puede que libere la memoria de área de almacenamiento de bloqueo .. java -Xms512m -Xmx1024m -cp simple.jar

Espero que funcione bien ahora ... :-)


Recientemente me enfrenté a este problema. Tengo 3 aplicaciones Java que comienzan con un tamaño de almacenamiento de 1024 mo 1280 m. Java está mirando el espacio disponible en el intercambio, y si no hay suficiente memoria disponible, sale el jvm.

Para resolver el problema, tuve que finalizar varios programas que tenían una gran cantidad de memoria virtual asignada.

Me estaba ejecutando en x86-64 Linux con un jvm de 64 bits.