Saltar al contenido

Java consume más memoria que el argumento Xmx

Este equipo especializado pasados algunos días de trabajo y recopilar de datos, obtuvimos la solución, queremos que resulte de gran utilidad para tu trabajo.

Solución:

Como se ha aludido en los comentarios y las respuestas, hay una serie de otros factores a tener en cuenta al medir el uso de la memoria JVM. Sin embargo, no creo que ninguna respuesta haya profundizado lo suficiente.

Descripción general de la memoria JVM

Vamos a responder a la pregunta “Me preguntaba para qué se utilizan esos 30 MB”. De frente. Para hacer esto, aquí hay una clase java simple:

// HelloWorld.java
public class HelloWorld 
    public static void main(String[] args) throws Exception 
        System.out.println("Hello world!");
        Thread.sleep(10000); // wait 10 seconds so we can get memory usage
    

Ahora compílelo y ejecútelo con restricciones de montón:

$ nohup java -Xms2m -Xmx2m HelloWorld & # run in background
$ ps aux | awk 'NR==1; /[H]elloWorld/'
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
chaospie  6204  6.0  0.1 2662860 23040 pts/2   Sl   19:15   0:00 java -Xms2m -Xmx2m HelloWorld

Al observar el RSS (tamaño del conjunto residente, o cuánta memoria está usando este proceso), vemos que el proceso de la JVM está usando aproximadamente 23 MB de memoria. Para ver por qué, hagamos un análisis. La forma más rápida de obtener una buena descripción general es activar NativeMemorytracking utilizar el jcmd instrumentos VM.native_memory mando. Entonces, ejecutemos nuestra aplicación nuevamente:

$ nohup java -XX:NativeMemoryTracking=summary -Xms2M -Xmx2M HelloWorld &
[2] 6661
nohup: ignoring input and appending output to 'nohup.out'

$ ps aux | awk 'NR==1; /[H]elloWorld/'
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
chaospie  6661  5.0  0.1 2662860 23104 pts/2   Sl   19:21   0:00 java -XX:NativeMemoryTracking=summary -Xms2M -Xmx2M HelloWorld

$ jcmd 6661 VM.native_memory summary
6661:

Native Memory Tracking:

Total: reserved=1360145KB, committed=61177KB
-                 Java Heap (reserved=2048KB, committed=2048KB)
                            (mmap: reserved=2048KB, committed=2048KB)

-                     Class (reserved=1066093KB, committed=14189KB)
                            (classes #402)
                            (malloc=9325KB #146)
                            (mmap: reserved=1056768KB, committed=4864KB)

-                    Thread (reserved=20646KB, committed=20646KB)
                            (thread #21)
                            (stack: reserved=20560KB, committed=20560KB)
                            (malloc=62KB #110)
                            (arena=23KB #40)

-                      Code (reserved=249632KB, committed=2568KB)
                            (malloc=32KB #299)
                            (mmap: reserved=249600KB, committed=2536KB)

-                        GC (reserved=10467KB, committed=10467KB)
                            (malloc=10383KB #129)
                            (mmap: reserved=84KB, committed=84KB)

-                  Compiler (reserved=132KB, committed=132KB)
                            (malloc=1KB #21)
                            (arena=131KB #3)

-                  Internal (reserved=9453KB, committed=9453KB)
                            (malloc=9421KB #1402)
                            (mmap: reserved=32KB, committed=32KB)

-                    Symbol (reserved=1358KB, committed=1358KB)
                            (malloc=902KB #86)
                            (arena=456KB #1)

-    Native Memory Tracking (reserved=143KB, committed=143KB)
                            (malloc=86KB #1363)
                            (tracking overhead=57KB)

-               Arena Chunk (reserved=175KB, committed=175KB)
                            (malloc=175KB)

Regiones de memoria

Vamos a romperlo 1:

  • Montón de Java : este es el montón –
  • Clase : este es Metaespacio, asumiendo que está usando java 8.
  • Hilo : esto muestra el número de subprocesos y el uso total de mem de los subprocesos (tenga en cuenta que el stack en esta sección refleja el Xss valor multiplicado por el número de subprocesos, puede obtener el valor predeterminado -Xssvalor con java -XX:+PrintFlagsFinal -version |grep ThreadStackSize).
  • Código : la caché de código: esto es utilizado por JIT (Just In Time Compiler) para almacenar en caché el código compilado.
  • GC : espacio utilizado por el recolector de basura.
  • Compilador : espacio utilizado por el JIT al generar código.
  • Simbolos : esto es para símbolos, nombres de campo, firmas de métodos, etc.
  • Seguimiento de memoria nativa : memoria utilizada por el propio rastreador de memoria nativa.
  • Arena Chunk : esto está relacionado con las arenas malloc 2.

¡Mucho más que el montón!

Reservado, comprometido y RSS

Tenga en cuenta que cada región tiene un committed y un reserved sección. Para ser breve
reserved es lo que puede crecer y committed es lo que actualmente está comprometido para ser utilizado. Por ejemplo, vea el Java Heap sección: Java Heap (reserved=2048KB, committed=2048KB), reserved es nuestro
-Xmx valor y comprometido sería nuestro -Xms value, en este caso son iguales.

Tenga en cuenta también que el total committed tamaño: no refleja el uso real informado por RSS (o la columna RES en top). La razón por la que difieren es que RSS muestra el tamaño de todas las páginas de memoria que han estado y todavía están en uso. en la memoria física, mientras que committed muestra la memoria que se utiliza, incluida la que no está en la memoria física 3.

Hay mucho más en esto, sin embargo, la gestión de la memoria de JVM y del sistema operativo es un tema complejo, por lo que espero que esto responda a su pregunta al menos en un alto nivel.


  1. Consulte https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/tooldescr022.html
  2. De los documentos de seguimiento de memoria nativa de JVM (https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/tooldescr007.html#BABJGHDB):

Arena es una parte de la memoria asignada mediante malloc. La memoria se libera de estos fragmentos de forma masiva, al salir de un ámbito o al salir de un área de código. Estos fragmentos se pueden reutilizar en otros subsistemas para contener memoria temporal, por ejemplo, asignaciones previas al subproceso. La política de Arena malloc garantiza que no se produzcan pérdidas de memoria. Entonces Arena se rastrea como un todo y no como objetos individuales. No se puede rastrear cierta cantidad de memoria inicial.

  1. Entrar en la diferencia entre la memoria RSS, reservada y comprometida sería demasiado aquí, la administración de la memoria del sistema operativo es un tema complejo, pero consulte esta respuesta para obtener una buena descripción general.

Java se ejecuta en una máquina virtual, en lugar de hacerlo directamente en su hardware. Esto significa que esta máquina necesita su propia memoria para funcionar. Los 5 MB que le permitió a su programa probablemente significan que la máquina virtual Java (JVM) está utilizando otros 26 MB.

valoraciones y comentarios

Tienes la opción de añadir valor a nuestro contenido dando tu veteranía en las interpretaciones.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)


Tags : / /

Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *