GNU/Linux >> Tutoriales Linux >  >> Linux

Creciente uso de memoria residente (RSS) de Java Process

Tuve el mismo problema. Este es un problema conocido con glibc>=2.10

La cura es establecer esta variable env export MALLOC_ARENA_MAX=4

Artículo de IBM sobre la configuración de MALLOC_ARENA_MAXhttps://www.ibm.com/developerworks/community/blogs/kevgrig/entry/linux_glibc_2_10_rhel_6_malloc_may_show_excessive_virtual_memory_usage?lang=en

Busque MALLOC_ARENA_MAX en Google o búsquelo en SO para encontrar muchas referencias.

Es posible que desee ajustar también otras opciones de malloc para optimizar la fragmentación de la memoria asignada:

# tune glibc memory allocation, optimize for low fragmentation
# limit the number of arenas
export MALLOC_ARENA_MAX=2
# disable dynamic mmap threshold, see M_MMAP_THRESHOLD in "man mallopt"
export MALLOC_MMAP_THRESHOLD_=131072
export MALLOC_TRIM_THRESHOLD_=131072
export MALLOC_TOP_PAD_=131072
export MALLOC_MMAP_MAX_=65536

También es posible que haya una pérdida de memoria nativa. Un problema común son las fugas de memoria nativa causadas por no cerrar un ZipInputStream /GZIPInputStream .

Una forma típica en que un ZipInputStream se abre mediante una llamada a Class.getResource /ClassLoader.getResource y llamando openConnection().getInputStream() en el java.net.URL instancia o llamando a Class.getResourceAsStream /ClassLoader.getResourceAsStream . Uno debe asegurarse de que estas corrientes siempre se cierren.

Algunas bibliotecas de código abierto de uso común han tenido errores que filtran java.util.zip.Inflater sin cerrar o java.util.zip.Deflater instancias. Por ejemplo, la biblioteca Nimbus Jose JWT solucionó una pérdida de memoria relacionada en la versión 6.5.1. Java JWT (jjwt) tenía un error similar que se solucionó en la versión 0.10.7. El patrón de error en estos 2 casos fue el hecho de que las llamadas a DeflaterOutputStream.close() y InflaterInputStream.close() no llamar Deflater.end() /Inflater.end() cuando un Deflater /Inflater se proporciona una instancia. En esos casos, no es suficiente verificar el código de las transmisiones que se están cerrando. Cada Deflater /Inflater las instancias creadas en el código deben tener un manejo que .end() recibe una llamada.

Una forma de verificar las fugas de Zip*Stream es obtener un volcado de pila y buscar instancias de cualquier clase con "zip", "Inflater" o "Deflater" en el nombre. Esto es posible en muchas herramientas de análisis de volcado de pila, como Yourkit Java Profiler, JProfiler o Eclipse MAT. También vale la pena verificar los objetos en estado de finalización ya que, en algunos casos, la memoria se libera solo después de la finalización. Es útil buscar clases que puedan usar bibliotecas nativas. Esto también se aplica a las bibliotecas TLS/ssl.

Hay una herramienta OSS llamada leakchecker de Elastic que es un agente Java que se puede usar para encontrar las fuentes de java.util.zip.Inflater instancias que no han sido cerradas (.end() no llamado).

Para fugas de memoria nativa en general (no solo para fugas de bibliotecas zip), puede usar jemalloc para depurar fugas de memoria nativa habilitando el perfilado de muestreo de malloc especificando la configuración en MALLOC_CONF Variable ambiental. Las instrucciones detalladas están disponibles en esta entrada de blog:http://www.evanjones.ca/java-native-leak-bug.html. Esta publicación de blog también tiene información sobre el uso de jemalloc para depurar una fuga de memoria nativa en aplicaciones Java. También hay una publicación de blog de Elastic que presenta a jemalloc y menciona el verificador de fugas, la herramienta que Elastic ha abierto para rastrear los problemas causados ​​por los recursos de inflador de zip sin cerrar.

También hay una publicación de blog sobre una pérdida de memoria nativa relacionada con ByteBuffers. Java 8u102 tiene una propiedad de sistema especial jdk.nio.maxCachedBufferSize para limitar el problema de caché descrito en esa publicación de blog.

-Djdk.nio.maxCachedBufferSize=262144

También es bueno verificar siempre los identificadores de archivos abiertos para ver si la pérdida de memoria es causada por una gran cantidad de archivos mmap:ed. En Linux lsof se puede usar para listar archivos abiertos y sockets abiertos:

lsof -Pan -p PID

El informe del mapa de memoria del proceso también podría ayudar a investigar las fugas de memoria nativa

pmap -x PID

Para los procesos de Java que se ejecutan en Docker, debería ser posible ejecutar el comando lsof o pmap en el "host". Puede encontrar el PID del proceso en contenedor con este comando

docker inspect --format '{{.State.Pid}}' container_id

También es útil obtener un volcado de subprocesos (o usar jconsole/JMX) para verificar la cantidad de subprocesos, ya que cada subproceso consume 1 MB de memoria nativa para su pila. Una gran cantidad de subprocesos usaría mucha memoria.

También hay seguimiento de memoria nativa (NMT) en la JVM. Eso podría ser útil para verificar si es la propia JVM la que está utilizando la memoria nativa.

La herramienta jattach también se puede usar en un entorno contenedorizado (docker) para desencadenar volcados de subprocesos o volcados de pila desde el host. También puede ejecutar comandos jcmd que se necesitan para controlar NMT.


Linux
  1. Uso de memoria de Linux

  2. Linux:¿limitar el uso de memoria para un solo proceso de Linux?

  3. ¿Herramienta que permite el registro del uso de la memoria?

  4. Uso máximo de memoria de un proceso Linux/Unix

  5. Uso de memoria del proceso actual en C

¿Cómo puedo medir el uso de memoria real de una aplicación o proceso?

¿Recuperar el uso de la CPU y el uso de la memoria de un solo proceso en Linux?

Limitar el uso de memoria/CPU de proceso en Linux

Determinar correctamente el uso de memoria en Linux

Cuando un proceso se bifurca, ¿se copia su memoria virtual o residente?

Ubuntu Linux:procesamiento de memoria de intercambio y uso de memoria