La herramienta de análisis de JVM que viene con el JDK

Desbordamiento de memoria, escena célebre propiamente dicha;

1. Antecedentes comerciales

Para los servicios de archivos en una arquitectura distribuida, debido a la gran cantidad de operaciones de flujo de E/S involucradas, es fácil causar excepciones relacionadas con JVM, especialmente el problema del desbordamiento de memoria;

En la iteración de la última versión, el escenario de procesamiento comercial real es casi el mismo que el anterior. Debido a la adición de acciones de procesamiento por lotes en el servicio de archivos, el error que ha estado oculto durante mucho tiempo se despierta directamente, que es el más desbordamiento de memoria común;

La causa del problema: después de que el documento de Word completa el reconocimiento de contenido, se convierte en un archivo pdf y luego la página se divide en un conjunto de imágenes.En este proceso complejo y largo, hay un contenedor de matriz que no es destruido;

Solución: analice el archivo de volcado de la JVM, ubique la causa raíz del problema OOM, combine el análisis de registro anormal del servicio de archivos y agregue la acción de liberación del recurso para resolver el problema;

2. Directorio Jdk-Bin

Para un número considerable de novatos, ver que los problemas de la JVM son errores ignorantes. De hecho, este tipo de mentalidad no es necesaria. A partir de la experiencia de desarrollo de varios años en el lugar de trabajo, los problemas de la JVM se pueden dividir aproximadamente en dos tipos:

  • Solución fácil para el desarrollo: puede actualizar los recursos de memoria o ajustar la asignación, u optimizar los programas para administrar y liberar recursos relacionados, que es el método más utilizado;
  • Fácil solución al desarrollo: debido a la falta de experiencia, los principales errores en el programa conducen a excepciones de JVM, que a su vez provocan una serie de reacciones en cadena.Este tipo de rebote no será Jedi, sino solo plumas de pollo;

Cuando se resuelven las excepciones de JVM convencionales, generalmente se confía en las herramientas básicas del JDK para completar la ubicación del problema, a fin de analizar y resolver el problema, pero esto requiere un uso experto de las herramientas básicas, y muchas de las capacidades propias de JDK a menudo se ignoran. ;

En el directorio bin de jdk, hay muchas herramientas integradas que se pueden usar para analizar la JVM;

El anterior es un directorio basado en jdk1.8 , y hay muchos comandos que se usan a menudo en el desarrollo. Centrémonos en el inicio y la operación de un microservicio, y echemos un vistazo al uso de herramientas JVM basadas en JDK;

3. Herramientas de línea de comandos

1. comando jps

jps : herramienta de estado de proceso de máquina virtual, este comando se usa a menudo en la implementación del entorno Java y la visualización de inicio del servicio.Primero, inicie un microservicio de fachada localmente y luego ejecute la consulta en la línea de comando;

  • jps: La salida predeterminada del comando es el ID del proceso y el nombre de la clase principal de la aplicación;
  • -l: Muestra el ID del proceso y la ruta completa de la clase principal de la aplicación;
  • -v:输出向jvm传递的参数,此处展示为idea中显式配置的VM-options参数,其他内容自行查看即可;
  • -m:输出向main方法传递的参数,服务启动前可以在idea的Program-arguments配置;
$ jps
1281 FacadeApp

$ jps -l
1281 com.explore.facade.FacadeApp

$ jps -v
1281 FacadeApp -Xms128m -Xmx256m -XX:MaxNewSize=256m -XX:MaxPermSize=256m

$ jps -m
1281 FacadeApp hello,main-method
复制代码

2、jinfo命令

jinfo:在命令后面带pid进程号,可以输出指定进程的配置信息,在应用启动时通常不会指定过多的配置参数,就可以使用该命令查询很多参数的默认值;该命令还可以在运行时动态调整部分参数,只是很少被使用;

$ jinfo 1281            # 只粘贴个别参数
Java System Properties: # 系统参数
    java.runtime.version=1.8.0_144-b01
    file.encoding=UTF-8
    sun.java.command=com.explore.facade.FacadeApp hello,main-method
    
VM Flags:               # 虚拟机参数
    -XX:InitialHeapSize=134217728 -XX:MaxHeapSize=268435456 -XX:MaxNewSize=267911168
    
VM Arguments:           # 运行时参数
    jvm_args: -Xms128m -Xmx256m -XX:MaxNewSize=256m -XX:MaxPermSize=256m
    java_command: com.explore.facade.FacadeApp hello,main-method

$ jinfo -sysprops 1281  # 只输出【Java System Properties】参数

$ jinfo -flags 1281     # 只输出【VM Flags】参数
复制代码

3、jstat命令

jstat:以指定的频率输出JVM的监控指标,下述命令输出内存占用和GC相关信息,每隔3秒输出一次,连续打印5次;由于这里只是启动一个简单的微服务,没有执行业务逻辑,所以各项指标比较平稳;

$ jstat -gcutil 1281 3000 5
S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT    CGC    CGCT     GCT   
0.00   0.00  57.97  64.16  92.82  88.75    3    0.028     9    0.516     -        -    0.544
0.00   0.00  57.97  64.16  92.82  88.75    3    0.028     9    0.516     -        -    0.544
复制代码

该命令是比较常用的,这里各项指标的统计逻辑,在tools.jar包中有jstat_options参考文档,相对路径sun/tools/jstat/resources/目录下;

option gcutil {
  column {
    header "^S0^"	/* Survivor 0 Space - Percent Used */
    data (1-((sun.gc.generation.0.space.1.capacity - sun.gc.generation.0.space.1.used)/sun.gc.generation.0.space.1.capacity)) * 100
  }
  column {
    header "^S1^"	/* Survivor 1 Space - Percent Used */
    data (1-((sun.gc.generation.0.space.2.capacity - sun.gc.generation.0.space.2.used)/sun.gc.generation.0.space.2.capacity)) * 100
  }
  ......
}
复制代码

4、jstack命令

jstack:输出指定进程当前时刻在JVM中的线程信息,为了清楚的展示其效果,在服务启动时创建线程死锁,然后通过该命令就会把发生死锁的线程打印出来,通过输出可以发现两条互相等待的线程信息;

$ jstack 1281
Found one Java-level deadlock:
=============================
"test-thread-02":
  waiting for ownable synchronizer 0x00000007b00a35d0, (a java.util.concurrent.locks.ReentrantLock$NonfairSync),
  which is held by "test-thread-01"
"test-thread-01":
  waiting for ownable synchronizer 0x00000007b00a35a0, (a java.util.concurrent.locks.ReentrantLock$NonfairSync),
  which is held by "test-thread-02"

Java stack information for the threads listed above:
===================================================
"test-thread-02":
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x00000007b00a35d0> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)

"test-thread-01":
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x00000007b00a35a0> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)

Found 1 deadlock.
复制代码

5、jmap命令

jmap:可以输出指定进程的内存中对象映射信息,或者堆的关键信息、内存的使用统计、GC算法、配置、类的实例信息及内存占用等,该命令在解决JVM问题时也经常使用;

$ jmap 1281

$ jmap -heap 1281
Heap Configuration:
   MinHeapFreeRatio         = 0
   MaxHeapFreeRatio         = 100
   MaxHeapSize              = 536870912 (512.0MB)
   
Heap Usage:
    PS Young Generation
    Eden Space:
    From Space:
    To Space:
    PS Old Generation

$ jmap -histo:live 1281
 num     #instances         #bytes  class name
----------------------------------------------
1311:             1             32  com.explore.facade.FacadeApp$$EnhancerBySpringCGLIB$$313d9e3
复制代码

四、可视化工具

1、jconsole

Java内置的JVM性能监控工具,在熟悉上述的命令行工具之后,对于该可视化工具的使用不会太陌生,在命令中可以查看到的默认参数或者应用自定义配置,在该工具中也可以找到,并且以图形化的方式呈现;

$ jconsole  # 通过该命令会唤起jconsole界面
复制代码

这里选择线程一栏,可以直观的看到线程数量的变化曲线,也可以在下方查看某个线程的具体信息,并且可以通过检测死锁功能,发现在服务中创建的test-thread-01和test-thread-02两条线程;

2、visualvm

VisualVM作为解决JVM问题的常用工具,集成的功能丰富且强大,此处通过Idea插件的方式启动FacadeApp微服务,在进程主页可以看到自定义的配置,线程一栏因为检测到死锁直接给到异常提示;

在监视一栏可以通过【堆dump】查看详细的信息,可以查看类的实例数和大小,并且完成了结果排序和占用统计;此处信息在定位和解决JVM问题时非常重要;

对于JVM的监控工具来说,其能力与常用的命令行语法差异很小,并且这些命令在jdk中tools.jar包也可以找到其对应的类,对于一些更高级的监控平台来说,例如Kuboard、Skywalking等,也对这些底层能力做了集成,其原理应该也是大同小异。

五、参考源码

编程文档:
https://gitee.com/cicadasmile/butte-java-note

应用仓库:
https://gitee.com/cicadasmile/butte-flyer-parent
复制代码

Supongo que te gusta

Origin juejin.im/post/7158238203537784868
Recomendado
Clasificación