Limitar la memoria de proceso de jvm en ubuntu

Sé que hay las mismas preguntas como esta preguntadas y respondidas. No estoy satisfecho con las respuestas, así que permítanme poner en más detalles los mensajes aquí.

Intento iniciar mi aplicación con -Xmx128m -Xms32m -XX:MaxPermSize=64m JVM: -Xmx128m -Xms32m -XX:MaxPermSize=64m . Cuando se inició la aplicación y cat /proc/10413/status el uso de la memoria escribiendo cat /proc/10413/status , ¡y encontré que vmsize es más de 600512 kB! que es mucho más grande que mi configuración. Me gustaría saber cómo limitar el uso de la memoria jvm del proceso.

 Name: java State: S (sleeping) Tgid: 10413 Pid: 10413 PPid: 1 TracerPid: 0 Uid: 1001 1001 1001 1001 Gid: 1007 1007 1007 1007 FDSize: 128 Groups: 1001 1007 **VmPeak: 728472 kB** **VmSize: 600512 kB** VmLck: 0 kB VmHWM: 298300 kB VmRSS: 280912 kB VmData: 647804 kB VmStk: 140 kB VmExe: 36 kB VmLib: 13404 kB VmPTE: 808 kB VmSwap: 0 kB Threads: 33 SigQ: 0/31522 SigPnd: 0000000000000000 ShdPnd: 0000000000000000 SigBlk: 0000000000000000 SigIgn: 0000000000000000 SigCgt: 2000000181005ccf CapInh: 0000000000000000 CapPrm: 0000000000000000 CapEff: 0000000000000000 CapBnd: ffffffffffffffff Cpus_allowed: f Cpus_allowed_list: 0-3 Mems_allowed: 00000000,00000001 Mems_allowed_list: 0 voluntary_ctxt_switches: 3 nonvoluntary_ctxt_switches: 2 

No puede controlar lo que desea controlar , -Xmx solo controla el Heap de Java, no controla el consumo de memoria nativa por parte de la JVM, que se consume de forma completamente diferente en función de la implementación.

Del siguiente artículo Gracias por la memoria (Comprender cómo la JVM usa memoria nativa en Windows y Linux)

El mantenimiento del recolector de montones y basura utiliza memoria nativa que no puede controlar.

Se requiere más memoria nativa para mantener el estado del sistema de administración de memoria que mantiene el almacenamiento dynamic de Java. Las estructuras de datos deben asignarse para rastrear el almacenamiento gratuito y registrar el progreso al recolectar la basura. El tamaño exacto y la naturaleza de estas estructuras de datos varía con la implementación, pero muchas son proporcionales al tamaño del montón.

y el comstackdor JIT usa memoria nativa al igual que javac

La comstackción de bytecode usa memoria nativa (de la misma manera que un comstackdor estático como gcc requiere memoria para ejecutarse), pero tanto la entrada (el bytecode) como la salida (el código ejecutable) del JIT también deben almacenarse en la memoria nativa. Las aplicaciones Java que contienen muchos métodos comstackdos JIT usan más memoria nativa que las aplicaciones más pequeñas.

y luego tienes los cargadores de clases que usan memoria nativa

Las aplicaciones Java están compuestas por clases que definen la estructura del objeto y la lógica del método. También usan clases de las bibliotecas de la clase de tiempo de ejecución de Java (como java.lang.String) y pueden usar bibliotecas de terceros. Estas clases deben almacenarse en la memoria durante el tiempo que estén siendo utilizadas. Cómo se almacenan las clases varía según la implementación.

Ni siquiera comenzaré a citar la sección sobre Threads, creo que se entiende que -Xmx no controla lo que usted cree que controla, sino que controla el montón de JVM, no todo va en el montón de JVM, y el montón ocupa todo forma más memoria nativa de lo que especifiques para la administración y la contabilidad.

Al igual que cualquier otro proceso en Linux, puede limitar el uso de memoria del proceso de JVM (por ejemplo, a 4 GB):

 $ ulimit -v 4194304 $ java ... # execute your Java program 

(Técnicamente esto es en realidad la memoria virtual, que es un límite superior para el uso real de la memoria. Pero ulimit aparentemente no funciona con el uso real de la memoria RAM ) .

Esto hará que las asignaciones de memoria por encima del límite fallen, lo que probablemente resultará en un OutOfMemoryError y en que su aplicación salga.