¿Herramienta de línea de comandos para encontrar el tamaño de almacenamiento dinámico de Java y la memoria utilizada (Linux)?

171

¿Existe una herramienta de línea de comandos (Linux) para verificar el tamaño de almacenamiento dinámico (y la memoria utilizada) de una aplicación Java?

Lo he intentado a través de jmap. Pero da información. sobre áreas de memoria interna como Eden / PermGen, etc., que no me son útiles.

Estoy buscando algo como:

  • Memoria máxima: 1 GB
  • Memoria mínima: 256 MB
  • Memoria de montón: 700 MB
  • Memoria utilizada: 460 MB

Eso es todo. Sé que puedo ver esto en JConsole, etc., pero necesito una herramienta de línea de comandos (no puedo habilitar JMX, etc.)

¿Conoces alguna herramienta / comando?

Jaspe
fuente

Respuestas:

150

Cada proceso Java tiene un pid, que primero debe encontrar con el jpscomando.

Una vez que tenga el pid, puede usarlo jstat -gc [insert-pid-here]para buscar estadísticas del comportamiento del montón de basura recolectada.

  • jstat -gccapacity [insert-pid-here] presentará información sobre la generación de agrupaciones de memoria y capacidades de espacio.

  • jstat -gcutil [insert-pid-here]presentará la utilización de cada generación como un porcentaje de su capacidad. Útil para obtener una vista rápida del uso.

Vea los documentos de jstat en el sitio de Oracle.

agricultor1992
fuente
11
¿Hay alguna recomendación sobre las opciones que jstatse deben usar para verificar solo el uso general de la memoria de una JVM? Supongamos que comienza la JVM con Xms=4gy Xmx=4gy desea ver, ¿cuánta memoria de eso ya se utiliza?
basZero
1
"jstat -gcutil <pid> 250 N" fue muy útil para tomar N muestras con intervalos de 250 ms y mostrar la salida como porcentajes para los espacios correspondientes. Gracias.
Kerem
3
A tener en cuenta cita de jstatOracle Java 8 manual de la página : This command is experimental and unsupported.
patryk.beza
1
awk 'print {$3+$4+$6+$8}'puede imprimir el uso resumido en las columnas jstat de Java 8
cybersoft
Tuve problemas con las otras respuestas, pero un básico ps -ef | grep javame mostró los argumentos vm, que en mi caso incluían el valor -Xmx, que era todo lo que necesitaba.
xdhmoore
66

jvmtop es una herramienta de línea de comandos que proporciona una vista en vivo de varias métricas, incluido el montón.

Ejemplo de salida del modo de visión general de VM:

 JvmTop 0.3 alpha (expect bugs)  amd64  8 cpus, Linux 2.6.32-27, load avg 0.12
 http://code.google.com/p/jvmtop

  PID MAIN-CLASS      HPCUR HPMAX NHCUR NHMAX    CPU     GC    VM USERNAME   #T DL
 3370 rapperSimpleApp  165m  455m  109m  176m  0.12%  0.00% S6U37 web        21
11272 ver.resin.Resin [ERROR: Could not attach to VM]
27338 WatchdogManager   11m   28m   23m  130m  0.00%  0.00% S6U37 web        31
19187 m.jvmtop.JvmTop   20m 3544m   13m  130m  0.93%  0.47% S6U37 web        20
16733 artup.Bootstrap  159m  455m  166m  304m  0.12%  0.00% S6U37 web        46
MRalwasser
fuente
De hecho, es una gran herramienta, una especie de htop pero con métricas de jstat. Gracias por su sugerencia, @MRalwasser.
oski86
65

Este comando muestra los tamaños de almacenamiento dinámico configurados en bytes.

java -XX:+PrintFlagsFinal -version | grep HeapSize

Funciona en Amazon AMI en EC2 también.

Atma
fuente
27
Esto no responde a la pregunta, que específicamente pregunta cómo verificar el uso del montón de un proceso. El comando aquí enumera los valores predeterminados de JVM en todos los procesos.
Madbreaks
10
Sin embargo, es una respuesta muy útil para mí venir a esta página a través de la búsqueda de Google sobre cómo encontrar el tamaño de almacenamiento dinámico global.
Johan
@jumping_monkey no indirecto, incorrecto. Si lo que estás diciendo es cierto, la respuesta debe ser editada o no dudes en agregar una nueva respuesta.
Madbreaks
43

Pruebe esto, funcionó en Ubuntu y RedHat:

java -XX:+PrintFlagsFinal -version | grep -iE 'HeapSize|PermSize|ThreadStackSize'

Para ventanas:

java -XX:+PrintFlagsFinal -version | findstr /i "HeapSize PermSize ThreadStackSize"

Para Mac

java -XX:+PrintFlagsFinal -version | grep -iE 'heapsize|permsize|threadstacksize'

La salida de todos estos comandos se asemeja a la salida a continuación:

uintx InitialHeapSize                          := 20655360        {product}
uintx MaxHeapSize                              := 331350016       {product}
uintx PermSize                                  = 21757952        {pd product}
uintx MaxPermSize                               = 85983232        {pd product}
intx ThreadStackSize                           = 1024            {pd product}
java version "1.7.0_05"
Java(TM) SE Runtime Environment (build 1.7.0_05-b05)
Java HotSpot(TM) 64-Bit Server VM (build 23.1-b03, mixed mode)

Para encontrar el tamaño en MB, divida el valor con (1024 * 1024).

padipista
fuente
¿Cómo encontrar el uso de memoria separado por montón, permsize, ... de un proceso específico de Java por pid?
Gary Gauh
3
@GaryGauh Este es el tamaño de almacenamiento dinámico predeterminado. Para encontrar el uso de la aplicación en ejecución, debe hacerlo dentro del código o puede usar jconsole. Esto es lo que sé que también debería haber muchas otras formas.
padippist
2
Úselo jstat -gc <vmid>para ejecutar aplicaciones.
Micha Wiedenmann
28

Sin usar JMX, que es lo que usan la mayoría de las herramientas, todo lo que puede hacer es usar

jps -lvm

e infiere que la configuración será de las opciones de la línea de comando.

No puede obtener información dinámica sin JMX de forma predeterminada, pero podría escribir su propio servicio para hacerlo.

Por cierto: prefiero usar VisualVM en lugar de JConsole.

Peter Lawrey
fuente
25

Hay una herramienta de línea de comandos con un aspecto visual: jvm-mon . Es una herramienta de monitoreo de JVM para la línea de comando que desaparece:

  • uso del montón, tamaño y máx.
  • procesos jvm
  • uso de CPU y GC
  • hilos superiores

Las métricas y los gráficos se actualizan mientras la herramienta está abierta.

Muestra: jvm-mon

Andrejs
fuente
1
Solo para notar que jvm-mon se ejecuta solo para Java8
tmanolatos
1
^ Hay una nueva versión que ahora también es compatible con Java 11.
Andrejs
11

Tarde en la fiesta, pero una solución muy simple es usar el script jpsstat.sh. Proporciona una simple memoria actual en vivo , memoria máxima y detalles de uso de la CPU .

  • Ir al proyecto GitHub y descargar el archivo jpsstat.sh
  • Haga clic derecho en jpsstat.sh y vaya a la pestaña de permisos y hágalo ejecutable
  • Ahora ejecute el script con el siguiente comando ./jpsstat.sh

Aquí está la salida de muestra del script:

=====  ======  =======  =======  =====
 PID    Name   CurHeap  MaxHeap  %_CPU
=====  ======  =======  =======  =====
2777   Test3      1.26     1.26    5.8
2582   Test1      2.52     2.52    8.3
2562   Test2      2.52     2.52    6.4
amarjeetAnand
fuente
no parece funcionar fuera de la caja en un SUSE Linux (línea 38: declarar: -A: opción no válida)
Chris
suena como si recibiera un error en la declaración de matriz asociativa que necesita bash> = 4. También otro problema puede deberse a ejecutar el script como "sh jpsstat.sh". Si es así, intente ejecutar el script como "./jpsstat.sh".
amarjeetAna
9

En mi caso, necesitaba verificar las banderas dentro de un contenedor acoplable que no tenía la mayoría de las utilidades básicas (ps, pstree ...)

Utilizando jpsobtuve el PID de la JVM ejecutándose (en mi caso 1) y luego jcmd 1 VM.flagsobtuve las banderas de la JVM en ejecución.

Depende de los comandos que tenga disponibles, pero esto podría ayudar a alguien. :)

froblesmartin
fuente
8

Desde Java8 y superior , puede usar el siguiente comando:

jcmd JAVA_PROCESS_IDGC.heap_info

Puede referirse a la suma de la memoria total y usada de la salida.

Sample Command And Output: jcmd 9758 GC.heap_info

PSYoungGen  total 1579520K, used 487543K [0x0000000751d80000, 0x00000007c0000000, 0x00000007c0000000)
  eden space 1354240K, 36% used [0x0000000751d80000,0x000000076f99dc40,0x00000007a4800000)
  from space 225280K, 0% used [0x00000007b2400000,0x00000007b2400000,0x00000007c0000000)
  to   space 225280K, 0% used [0x00000007a4800000,0x00000007a4800000,0x00000007b2400000)
ParOldGen       total 3610112K, used 0K [0x0000000675800000, 0x0000000751d80000, 0x0000000751d80000)
  object space 3610112K, 0% used [0x0000000675800000,0x0000000675800000,0x0000000751d80000)
Metaspace       used 16292K, capacity 16582K, committed 16896K, reserved 1064960K
  class space    used 1823K, capacity 1936K, committed 2048K, reserved 1048576K

Para obtener más detalles sobre el comando jcmd, visite el enlace: https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/tooldescr006.html

vaibhav gupta
fuente
1
Necesitas corregir tu comentario. GC.heap_info está disponible en Java 9 y superior. No está disponible en Java 8. Vea otro hilo aquí: stackoverflow.com/questions/41891127/…
Pavel Molchanov
@PavelMolchanov Puedo usar el comando en jdk1.8.0_172. /Library/Java/JavaVirtualMachines/jdk1.8.0_172.jdk/Contents/Home/bin/jcmd 98270 GC.heap_info. Por favor, si puede, agregue la información al hilo referido, así como no tengo suficiente reputación en este momento para agregar un comentario allí.
vaibhav gupta
¿Usas Mac? ¿Utiliza Oracle JDK? No sé cómo puede estar disponible en su jdk1.8.0_172, Oracle documentó esta característica solo en Java 9 y versiones posteriores: docs.oracle.com/javase/9/tools/jcmd.htm . No está en la documentación de Oracle JDK para Java 8. No se menciona en el enlace que proporcionó en la parte inferior: docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/…
Pavel Molchanov
Una pregunta más. Verifique la versión JDK que ejecuta el proceso 98270 en su ejemplo. jcmd obtiene comandos disponibles de JVM del proceso (en su caso 98270). Si el proceso 98270 se ejecuta con un JDK diferente (JDK 9 o superior), verá que el comando GC.heap_info disponible incluso en JCMD es de Java 8. Los comandos disponibles pueden ser diferentes para diferentes procesos. Para obtener los comandos disponibles, ejecute: jcmp <PID> help.
Pavel Molchanov
1
FWIW, GC.heap_infodefinitivamente está disponible en OpenJDK 8 también. ¿Quizás solo en versiones recientes? Estoy usando este: 8u191-b12-2ubuntu0.18.04.1
Por Lundberg
7

Cualquier enfoque debería darte aproximadamente el mismo número. Siempre es una buena idea asignar el montón utilizando -X..m -X..xtodas las generaciones. Luego puede garantizar y también hacer ps para ver qué parámetros se pasaron y, por lo tanto, se están utilizando.

Para los usos de memoria reales, también puede comparar aproximadamente VIRT (asignado y compartido) y RES (real utilizado) en comparación con los valores jstat:

Para Java 8, vea jstat para estos valores realmente significan. Suponiendo que ejecuta una clase simple sin mmap o procesamiento de archivos.

$ jstat -gccapacity 32277
 NGCMN    NGCMX     NGC     S0C   S1C       EC      OGCMN      OGCMX       OGC         OC       MCMN     MCMX      MC     CCSMN    CCSMX     CCSC    YGC    FGC
215040.0 3433472.0  73728.0  512.0  512.0  67072.0   430080.0  6867968.0   392704.0   392704.0      0.0 1083392.0  39680.0      0.0 1048576.0   4864.0   7225     2
$ jstat -gcutil 32277
  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
  6.25   0.00   7.96  18.21  98.01  95.29   7228   30.859     2    0.173   31.032

Max :

     NGCMX + S0C + S1C + EC    + OGCMX   + MCMX    + CCSMX
   3433472 + 512 + 512 + 67072 + 6867968 + 1083392 + 1048576 = 12 GB

(aproximadamente cerca y debajo de la memoria VIRT)

Max (Min, Usado):

215040 + 512 + 512 + 67072 + 430080  + 39680    +  4864  = ~ 1GB

(aproximadamente cerca de la memoria RES)

"No me cite sobre esto", pero la memoria VIRT está más o menos cerca de la memoria máxima asignada, pero siempre que la memoria utilizada esté libre / disponible en la memoria física, JVM no arroja una excepción de memoria. De hecho, la memoria máxima ni siquiera se compara con la memoria física en el inicio de JVM, incluso con el intercambio apagado en el sistema operativo. Aquí se discute una mejor explicación de qué memoria virtual realmente utiliza un proceso Java .

kisna
fuente
4

Primero obtenga la identificación del proceso, el primer número del proceso listado, de uno de los siguientes: (o simplemente use ps aux | grep java, si lo prefiere)

jps -lvm

Luego use la ID del proceso aquí:

jmap -heap $MY_PID 2>/dev/null | sed -ne '/Heap Configuration/,$p';
jmap -permstat $MY_PID
sjas
fuente
2

Usar el topcomando es la forma más simple de verificar el uso de memoria del programa. RESLa columna muestra la memoria física real que está ocupada por un proceso.

Para mi caso, tenía un archivo de 10g leído en Java y cada vez que salía de la excepción de memoria. Esto sucedió cuando el valor en la REScolumna alcanzó el valor establecido en la -Xmxopción. Luego, al aumentar la memoria usando la -Xmxopción, todo salió bien.

M. Mashaye
fuente
3
El comando top muestra cuánto sistema operativo se le da a la JVM. estos chicos se preguntan cómo podemos ver el uso del espacio dinámico dentro de JVM JVM está utilizando 10g no significa que el espacio de almacenamiento dinámico real esté lleno de datos de 10g, porque jvm casi nunca devuelve la memoria al sistema operativo desde el almacenamiento dinámico hasta que finaliza el proceso.
linehrr
2

En términos de tamaño de almacenamiento dinámico de Java, en Linux, puede usar

ps aux | grep java

o

ps -ef | grep java

y busque -Xms, -Xmx para averiguar el tamaño de almacenamiento dinámico inicial y máximo especificado.

Sin embargo, si -Xms o -Xmx están ausentes para el proceso Java que le interesa, significa que su proceso Java está utilizando los tamaños de almacenamiento dinámico predeterminados. Puede usar el siguiente comando para averiguar los tamaños predeterminados.

java -XX:+PrintFlagsFinal -version | grep HeapSize

o un jvm particular, por ejemplo,

/path/to/jdk1.8.0_102/bin/java -XX:+PrintFlagsFinal -version | grep HeapSize

y busque InitialHeapSize y MaxHeapSize, que está en bytes.

Yuci
fuente
1

Si usa jrockit, pruebe la herramienta de línea de comando jrcmd. Por ejemplo:

$ jrcmd 5127 print_memusage
5127:
Total mapped                  1074596KB           (reserved=3728KB)
-              Java heap       786432KB           (reserved=0KB)
-              GC tables        26316KB          
-          Thread stacks        13452KB           (#threads=34)
-          Compiled code         9856KB           (used=9761KB)
-               Internal          840KB          
-                     OS        15036KB          
-                  Other       146632KB          
-        Java class data        75008KB           (malloced=74861KB #103221 in 18709 classes)
- Native memory tracking         1024KB           (malloced=102KB #8)

Para obtener más comandos, como heap_diagnostics, use "jrcmd help" para enumerarlos.

https://blogs.oracle.com/jrockit/entry/why_is_my_jvm_process_larger_t

invitado
fuente
1
jstat -gccapacity javapid  (ex. stat -gccapacity 28745)
jstat -gccapacity javapid gaps frames (ex.  stat -gccapacity 28745 550 10 )

Ejemplo de O / P del comando anterior

NGCMN    NGCMX     NGC     S0C  
87040.0 1397760.0 1327616.0 107520.0 

NGCMN   Minimum new generation capacity (KB).
NGCMX   Maximum new generation capacity (KB).
NGC Current new generation capacity (KB).

Obtenga más detalles sobre esto en http://docs.oracle.com/javase/1.5.0/docs/tooldocs/share/jstat.html

Pravin
fuente
1

No existe una herramienta de este tipo hasta ahora para imprimir la memoria de almacenamiento dinámico en el formato que solicitó. La única y única forma de imprimir es escribir un programa java con la ayuda de Runtime Class ,

public class TestMemory {

public static void main(String [] args) {

    int MB = 1024*1024;

    //Getting the runtime reference from system
    Runtime runtime = Runtime.getRuntime();

    //Print used memory
    System.out.println("Used Memory:" 
        + (runtime.totalMemory() - runtime.freeMemory()) / MB);

    //Print free memory
    System.out.println("Free Memory:" 
        + runtime.freeMemory() / mb);

    //Print total available memory
    System.out.println("Total Memory:" + runtime.totalMemory() / MB);

    //Print Maximum available memory
    System.out.println("Max Memory:" + runtime.maxMemory() / MB);
}

}

referencia: https://viralpatel.net/blogs/getting-jvm-heap-size-used-memory-total-memory-using-java-runtime/

Gowtham Prasath
fuente
esto está mal. jmap -heap <pid> da esta información
vsingh
0

Encuentre la identificación del proceso de su proceso webapp / java desde arriba. Use jmap heap para obtener la asignación del montón. Probé esto en AWS-Ec2 para el frijol elástico

Puede ver en la imagen a continuación el almacenamiento dinámico máximo de 3GB para la aplicación

ingrese la descripción de la imagen aquí

vsingh
fuente