Expliqué mucha estructura de memoria JVM y creación de objetos. Estas son la base de JVM, pero el objetivo final es poder ajustarlas. A veces, la aplicación no responde y reporta OOM, pérdidas de memoria o muerte. Para resolver Estos problemas, es indispensable aprender algunas herramientas de línea de comandos que vienen con jdk. Con la base de estas herramientas, no solo reiniciará para resolver el problema cuando se encuentre con un problema, sino que puede comenzar desde Resolver los problemas de la aplicación en la causa raíz, mejorando así el poder interno del desarrollo de Java
En términos generales, las herramientas jdk más utilizadas son las siguientes:
- jps: ver todos los procesos de Java
- jstat: supervisa diversa información sobre el estado operativo de las máquinas virtuales
- jinfo: vea y ajuste varios parámetros de la máquina virtual en tiempo real
- jmap: generar una instantánea de almacenamiento dinámico
- jhat: Analiza el archivo de volcado de pila
- jstack: genera una instantánea del hilo de la máquina virtual en el momento actual
Uno, JDK viene con herramientas
jps
: Ver todos los procesos de Java
jps
(Estado de proceso de JVM) Mandatos de tipo UNIX ps
.
jps
: Muestra el nombre de la clase principal de ejecución de la máquina virtual y el ID único (identificador de máquina virtual local, LVMID) de estos procesos.
jps -q
: Solo genera el ID único de la máquina virtual local del proceso.
jps -l
: Muestra el nombre completo de la clase principal. Si el proceso está ejecutando el paquete Jar, genera la ruta Jar.
jps -v
: Muestra los parámetros de JVM cuando se inicia el proceso de la máquina virtual.
jps -m
: Muestra los parámetros pasados a la función main () del proceso Java.
jstat
: Supervisa información sobre el estado operativo de las máquinas virtuales
jstat (Herramienta de supervisión de estadísticas de JVM) es una herramienta de línea de comandos que se utiliza para supervisar información sobre el estado operativo de las máquinas virtuales. Puede mostrar información de clase, memoria, recolección de basura, compilación JIT y otros datos en ejecución en el proceso de la máquina virtual de forma local o remota (requiere soporte RMI del host remoto). En un servidor que no tiene una GUI y solo proporciona un texto sin formato entorno de consola, será la herramienta elegida para localizar problemas de rendimiento de la máquina virtual durante el funcionamiento.
jstat
Formato de comando:
jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
Por ejemplo, jstat -gc -h3 31736 1000 10
muestra un proceso de análisis con id 31736 gc caso, el registro se imprime una vez cada 1000ms, 10 veces para detener la impresión, imprimiendo el cabezal de los indicadores después de cada tres líneas.
Las opciones comunes son las siguientes:
jstat -class vmid
: Muestra información relacionada con ClassLoader;jstat -compiler vmid
: Muestra información relacionada con la compilación JIT;jstat -gc vmid
: Muestra información del montón relacionada con GC;jstat -gccapacity vmid
: Muestra la capacidad y el uso de cada generación;jstat -gcnew vmid
: Muestra información de nueva generación;jstat -gcnewcapcacity vmid
: Muestra el tamaño y uso de la nueva generación;jstat -gcold vmid
: Muestra las estadísticas de comportamiento de la generación anterior y la generación permanente, a partir de jdk1.8, esta opción solo indica la generación anterior porque la generación permanente ha sido eliminada;jstat -gcoldcapacity vmid
: Muestra el tamaño de la vejez;jstat -gcpermcapacity vmid
: Muestra el tamaño de la generación permanente A partir de jdk1.8, esta opción ya no existe porque se eliminó la generación permanente;jstat -gcutil vmid
: Muestra información sobre la recolección de basura;
Además, con -t
los parámetros enumerados se pueden agregar en una información de marca de tiempo que se emite para mostrar el tiempo de ejecución del programa.
jinfo
: Ver y ajustar varios parámetros de la máquina virtual en tiempo real.
jinfo vmid
: Muestra todos los parámetros y atributos del sistema del proceso JVM actual (la primera parte son los atributos del sistema y la segunda parte son los parámetros de la JVM).
jinfo -flag name vmid
: Muestra el valor específico del parámetro correspondiente al nombre. Por ejemplo, genere MaxHeapSize y verifique si el proceso jvm actual está habilitado para imprimir registros de GC ( -XX:PrintGCDetails
: modo de registro de GC detallado, ambos deshabilitados de manera predeterminada).
C:\Users\SnailClimb>jinfo -flag MaxHeapSize 17340
-XX:MaxHeapSize=2124414976
C:\Users\SnailClimb>jinfo -flag PrintGC 17340
-XX:-PrintGC
Con jinfo, puede modificar dinámicamente los parámetros de jvm sin reiniciar la máquina virtual. Especialmente el entorno en línea es particularmente útil, consulte el siguiente ejemplo:
jinfo -flag [+|-]name vmid
Encienda o apague el parámetro del nombre correspondiente.
C:\Users\SnailClimb>jinfo -flag PrintGC 17340
-XX:-PrintGC
C:\Users\SnailClimb>jinfo -flag +PrintGC 17340
C:\Users\SnailClimb>jinfo -flag PrintGC 17340
-XX:+PrintGC
jmap
: Generar instantánea de volcado de montón
jmap
El comando (Mapa de memoria para Java) se utiliza para generar instantáneas de volcado de pila. Si no usa el jmap
comando, para obtener el volcado de pila de Java, puede usar “-XX:+HeapDumpOnOutOfMemoryError”
parámetros, lo que permite que las máquinas virtuales generen automáticamente archivos de volcado después de que ocurra la excepción OOM, el comando de Linux puede kill -3
salir del proceso puede enviar una señal para obtener el volcado expediente.
jmap
La función de no es solo obtener el archivo de volcado, sino que también puede consultar la cola de ejecución del finalizador, el montón de Java y la información detallada de la generación permanente, como el uso de espacio, qué recopilador se usa actualmente, etc. Y jinfo
, como jmap
hay muchas funciones en la plataforma de Windows, también está restringida.
Ejemplo: Genere una instantánea del montón de una aplicación específica en el escritorio. Más tarde, puede analizar el archivo de pila con herramientas como jhat y Visual VM.
C:\Users\SnailClimb>jmap -dump:format=b,file=C:\Users\SnailClimb\Desktop\heap.hprof 17340
Dumping heap to C:\Users\SnailClimb\Desktop\heap.hprof ...
Heap dump file created
jhat
: Analiza el archivo de volcado de pila
jhat
Usado para analizar el archivo de volcado de memoria, establecerá un servidor HTTP / HTML para que los usuarios puedan ver los resultados del análisis en el navegador.
C:\Users\SnailClimb>jhat C:\Users\SnailClimb\Desktop\heap.hprof
Reading from C:\Users\SnailClimb\Desktop\heap.hprof...
Dump file created Sat May 04 12:30:31 CST 2019
Snapshot read, resolving...
Resolving 131419 objects...
Chasing references, expect 26 dots..........................
Eliminating duplicate references..........................
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.
Visite http: // localhost: 7000 /
jstack
: Genera una instantánea del hilo de la máquina virtual en el momento actual
jstack
El comando (Stack Trace para Java) se utiliza para generar una instantánea del hilo de la máquina virtual en el momento actual. Una instantánea de subproceso es una colección de pilas de métodos que ejecuta cada subproceso en la máquina virtual actual.
El propósito de generar una instantánea de subproceso es principalmente localizar la causa del bloqueo del subproceso durante mucho tiempo, como un punto muerto entre subprocesos, bucles infinitos y largas esperas causadas por la solicitud de recursos externos, que son todas razones por las que el subproceso se detiene mucho tiempo. Cuando un subproceso se detiene, al jstack
mirar la pila de llamadas de cada subproceso, puede saber qué está haciendo el subproceso que no responde en segundo plano o qué recursos está esperando.
A continuación se muestra el código para un interbloqueo de subprocesos. Aquí pasaremos jstack
un comando para verificar el punto muerto, la información de salida del punto muerto, encontrar el punto muerto del hilo.
public class DeadLockDemo {
private static Object resource1 = new Object();//资源 1
private static Object resource2 = new Object();//资源 2
public static void main(String[] args) {
new Thread(() -> {
synchronized (resource1) {
System.out.println(Thread.currentThread() + "get resource1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread() + "waiting get resource2");
synchronized (resource2) {
System.out.println(Thread.currentThread() + "get resource2");
}
}
}, "线程 1").start();
new Thread(() -> {
synchronized (resource2) {
System.out.println(Thread.currentThread() + "get resource2");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread() + "waiting get resource1");
synchronized (resource1) {
System.out.println(Thread.currentThread() + "get resource1");
}
}
}, "线程 2").start();
}
}
Producción
Thread[线程 1,5,main]get resource1
Thread[线程 2,5,main]get resource2
Thread[线程 1,5,main]waiting get resource2
Thread[线程 2,5,main]waiting get resource1
El subproceso A obtiene el bloqueo de monitor de resource1 a través de sincronizado (resource1), y luego Thread.sleep(1000);
duerme el subproceso A durante 1 s para permitir que se ejecute el subproceso B y luego obtener el bloqueo de monitor de resource2. El subproceso A y el subproceso B comienzan a solicitar recursos entre sí después de que han terminado de dormir, y luego los dos subprocesos caerán en un estado de espera el uno por el otro, lo que también produce un punto muerto.
Por jstack
análisis de comando:
C:\Users\SnailClimb>jps
13792 KotlinCompileDaemon
7360 NettyClient2
17396
7972 Launcher
8932 Launcher
9256 DeadLockDemo
10764 Jps
17340 NettyServer
C:\Users\SnailClimb>jstack 9256
Parte del resultado es el siguiente:
Found one Java-level deadlock:
=============================
"线程 2":
waiting to lock monitor 0x000000000333e668 (object 0x00000000d5efe1c0, a java.lang.Object),
which is held by "线程 1"
"线程 1":
waiting to lock monitor 0x000000000333be88 (object 0x00000000d5efe1d0, a java.lang.Object),
which is held by "线程 2"
Java stack information for the threads listed above:
===================================================
"线程 2":
at DeadLockDemo.lambda$main$1(DeadLockDemo.java:31)
- waiting to lock <0x00000000d5efe1c0> (a java.lang.Object)
- locked <0x00000000d5efe1d0> (a java.lang.Object)
at DeadLockDemo$$Lambda$2/1078694789.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
"线程 1":
at DeadLockDemo.lambda$main$0(DeadLockDemo.java:16)
- waiting to lock <0x00000000d5efe1d0> (a java.lang.Object)
- locked <0x00000000d5efe1c0> (a java.lang.Object)
at DeadLockDemo$$Lambda$1/1324119927.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
Found 1 deadlock.
Puede ver que jstack
el comando nos ha ayudado a obtener los detalles del punto muerto del hilo.