环境:

Tomcat + JDK

1、JDK自带监控工具

1.1 jps

用来查看Java程序进程的具体状态,包括进程ID,进程启动的路径及启动参数等等,与unix上的ps类似,只不过jps是用来显示java进程。

常用参数如下:

  1. -q: 忽略输出的类名、Jar名以及传递给main方法的参数,只输出pid
  2. -m: 输出传递给main方法的参数,如果是内嵌的VM则输出为nu17
  3. -1: 输出完全的包名,应用主类名,jar的完全路径名
  4. -v: 输出传给jvm的参数

注意:使用jps时的运行账户要和MM虚拟机启动的账户一致。若启动MM虚拟机是运行的账户为www,那使用jps指令时,也要使用www 用户去指定。sudo -u www jps

Example

查看已经运行的JMM进程的实际启动参数

  1. [root@localhost]# jps-v
  2. 38372 Jps -Dapp1ication.home=/usr/loca1/jdk -Xms8m38360 Bootstrap -
  3. Djava.uti7.1ogging.config.file=/data0/tomcat/conf/1ogging.properties -
  4. Djava.uti7.logging.manager=org.apache.juli.classLoaderLogManager -Xms4096m -Xmx4096m -XX:Permsize=1024m -XX:MaxPermsize=2048m -
  5. Djdk.tls.ephemera1DHKeysize=2048 -
  6. Djava.protoco1.hand1er.pkgs=org.apache.catalina.webresources -Dignore.endorsed.dirs= -Dcatalina.base=/data0/tomcat -
  7. Dcatalina.home=/data0/tomcat -Djava.io.tmpdir=/data0/tomcat/temp

1.2 jstack

istack用于打印出给定的java进程ID或远程调试服务的Java堆栈信息。jistack是非常有用的。打印出来的信息通常在运维的过程中被保存起来(保存故障现场),以供RD们去分析故障。

常用参数如下:

  1. jstack <pid>
  2. jstack [-1]<pid> #长列表.打印关于锁的附加信息
  3. jstack [-F] <pid> #当'jstack [-1] pid'没有响应的时候强制打印栈信息

1.3 jinfo

可以查看或修改运行时的MM进程的参数。

常用参数:

  1. jinfo [option] pid
  2. where <option> is one of:
  3. -fag <name> to print the value of the named vM flag
  4. -f1ag [+|-]<name> to enable or disab1e the named vM flag
  5. -flag <name>=<value> to set the named vM flag to the given value
  6. -f1ags to print vM flags

Exmaple:

  1. [root@e5e1149aa1c4 tomcat]# jinfo -flag MaxHeapSize 14
  2. -XX:MaxHeapSize=989855744
  3. # 动态更改JVM的最大栈值
  4. [root@e5e1149aa1c4 tomcat]# jinfo -flag MaxHeapSize=989855744 14
  5. Exception in thread "main" com.sun.tools.attach.AttachOperationFailedException: flag 'MaxHeapSize' cannot be changed
  6. at sun.tools.attach.LinuxVirtualMachine.execute(LinuxVirtualMachine.java:229)
  7. at sun.tools.attach.HotSpotVirtualMachine.executeCommand(HotSpotVirtualMachine.java:261)
  8. at sun.tools.attach.HotSpotVirtualMachine.setFlag(HotSpotVirtualMachine.java:234)
  9. at sun.tools.jinfo.JInfo.flag(JInfo.java:134)
  10. at sun.tools.jinfo.JInfo.main(JInfo.java:81)
  11. # jinfo 并不能动态的改变所有的JVM 参数。那到底有哪些参数能够被动态的改变呢?
  12. # java -XX:+PrintFlagsFinal -version 查看JVM的所有参数
  13. # java -XX:+PrintFlagsFinal -version | grep manageable 查看可以动态修改的参数
  14. # 查看可以动态修改的参数
  15. [root@4bc2f7c112e1 tomcat]# java -XX:+PrintFlagsFinal -version | grep manageable
  16. intx CMSAbortablePrecleanWaitMillis = 100 {manageable}
  17. intx CMSTriggerInterval = -1 {manageable}
  18. intx CMSWaitDuration = 2000 {manageable}
  19. bool HeapDumpAfterFullGC = false {manageable}
  20. bool HeapDumpBeforeFullGC = false {manageable}
  21. bool HeapDumpOnOutOfMemoryError = false {manageable}
  22. ccstr HeapDumpPath = {manageable}
  23. uintx MaxHeapFreeRatio = 100 {manageable}
  24. uintx MinHeapFreeRatio = 0 {manageable}
  25. bool PrintClassHistogram = false {manageable}
  26. bool PrintClassHistogramAfterFullGC = false {manageable}
  27. bool PrintClassHistogramBeforeFullGC = false {manageable}
  28. bool PrintConcurrentLocks = false {manageable}
  29. bool PrintGC = false {manageable}
  30. bool PrintGCDateStamps = false {manageable}
  31. bool PrintGCDetails = false {manageable}
  32. bool PrintGCID = false {manageable}
  33. bool PrintGCTimeStamps = false {manageable}
  34. java version "1.8.0_281"
  35. Java(TM) SE Runtime Environment (build 1.8.0_281-b09)
  36. Java HotSpot(TM) 64-Bit Server VM (build 25.281-b09, mixed mode)
  37. # 也只有以上这些值可以被动态修改,如下:
  38. # - 这里使用pid不同是由于我是用docker启动的tomcat,里面无法执行查看操作,查看宿主机映射
  39. [root@4bc2f7c112e1 tomcat]# jinfo -flag CMSWaitDuration=1900 15
  40. #查看,jinfo -flags查看VM的f1ags
  41. [root@k8s-master1 ~]# jinfo -flags 13325
  42. Attaching to process ID 13325, please wait...
  43. Debugger attached successfully.
  44. Server compiler detected.
  45. JVM version is 25.281-b09
  46. Non-default VM flags: -XX:CICompilerCount=3 -XX:CMSWaitDuration=1900 -XX:InitialHeapSize=62914560 -XX:MaxHeapSize=989855744 -XX:MaxNewSize=329777152 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=20971520 -XX:OldSize=41943040 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:+UseParallelGC
  47. Command line: -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.security.egd=file:/dev/./urandom -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dignore.endorsed.dirs= -Dcatalina.base=/usr/local/tomcat -Dcatalina.home=/usr/local/tomcat -Djava.io.tmpdir=/usr/local/tomcat/temp

1.4 jstat

主要利用MM内建的指令对java应用程序的资源和性能进行实时的命令行的监控,包括了对Heap size和垃圾回收状况的监控。常用指令:

  1. jstat -gc 15 1000 10
  2. #打印PID为15 JVM状态,一共打印10次,每次间隔时间为1s (1000ms)
  3. -gc用于查看VM中堆的垃圾收集情况的统计

注: jstat的用法超级强大,我们这里只是列举出列其中一个简单的应用。

Example

  1. [root@4bc2f7c112e1 tomcat]# jstat -gc 15 1000 10
  2. S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
  3. 2560.0 2560.0 0.0 2538.1 30720.0 703.1 40960.0 9312.4 18176.0 17591.1 2048.0 1925.5 3 0.023 0 0.000 0.023
  4. 2560.0 2560.0 0.0 2538.1 30720.0 703.1 40960.0 9312.4 18176.0 17591.1 2048.0 1925.5 3 0.023 0 0.000 0.023
  5. 2560.0 2560.0 0.0 2538.1 30720.0 703.1 40960.0 9312.4 18176.0 17591.1 2048.0 1925.5 3 0.023 0 0.000 0.023
  6. 2560.0 2560.0 0.0 2538.1 30720.0 703.1 40960.0 9312.4 18176.0 17591.1 2048.0 1925.5 3 0.023 0 0.000 0.023
  7. 2560.0 2560.0 0.0 2538.1 30720.0 703.1 40960.0 9312.4 18176.0 17591.1 2048.0 1925.5 3 0.023 0 0.000 0.023
  8. 2560.0 2560.0 0.0 2538.1 30720.0 703.1 40960.0 9312.4 18176.0 17591.1 2048.0 1925.5 3 0.023 0 0.000 0.023
  9. 2560.0 2560.0 0.0 2538.1 30720.0 703.1 40960.0 9312.4 18176.0 17591.1 2048.0 1925.5 3 0.023 0 0.000 0.023
  10. 2560.0 2560.0 0.0 2538.1 30720.0 703.1 40960.0 9312.4 18176.0 17591.1 2048.0 1925.5 3 0.023 0 0.000 0.023
  11. 2560.0 2560.0 0.0 2538.1 30720.0 703.1 40960.0 9312.4 18176.0 17591.1 2048.0 1925.5 3 0.023 0 0.000 0.023
  12. 2560.0 2560.0 0.0 2538.1 30720.0 703.1 40960.0 9312.4 18176.0 17591.1 2048.0 1925.5 3 0.023 0 0.000 0.023

JVM运维实用排查工具 - 图1

1.5 jvmtop

以上介绍的 ips、istack、jinfg等都是安装IDK时自带的系统分析工具,而jvmtop是一款开源的JMM工具。

它的下载地址如下: https://github.com/patric-r/jvmtop

顾名思义,它是一个只针对JMM的工具,展示的方式和unix的top命令相似.

ivmtop提供了两个视图,一个是概览视图,可以展示出当前机器的所有的MM的情况.还有一个视图是详情视图,展示一个JVM的详细情况

2、VirtualVM介绍

VisualVM是一款免费的性能分析工具。它通过jivmstat、IMX、SA (Serviceability Agent)服务性代理以及Attach APl等多种方式从程序运行时获得实时数据,从而进行动态的性能分析。同时,它能自动选择更快更轻量级的技术尽量减少性能分析对应用程序造成的影响,提高性能分析的精度。

2.1 安装VirtualVM

先在电脑上面安装jdk

到官网下载相应操作系统对应的软件.

官网地址: http://visualvm.github.io/

2.2 安装VirtualVM插件

https://www.bilibili.com/video/BV1pz4y1D73n?p=523&spm_id_from=pageDriver

  1. VisualVM插件中心提供很多插件以供安装

可以通过VisualVM应用程序安装,或者从VisualVM插件中心手动下载插件,然后离线安装。从VisualVM插件中心安装插件步骤:

  • 从主菜单中选择“工具”>“插件”。
  • 在“可用插件”标签中,选中该插件的“安装”复选框。单击”安装”。
  • 逐步完成插件安装程序。
  1. 离线安装插件
  • 到插件中心官网: http://visualvm.github.io/pluginscenters.html下载对应的VisualVM版本的插件
  • 从主菜单中选择“工具”>“插件”。
  • 在“已下载”标签中,点击”添加插件”按钮,选择已下载的插件文件(以.nbm结尾)打开。
  • 选中要打开的插件文件,并单击”安装”按钮,逐步完成插件安装程序。

2.3 如何监控JVM

那如何通过VisualVM去分析远程的JMM虚拟机里的信息呢?

首先要在IMM中开启相关配置,以供VisualIMM能够从中获取MM的信息,如何配置MM呢?这里以Tomcat为例:

  1. # 在Tomcat的catalina.sh或者是setenv.sh脚本中加上如下参数
  2. CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote
  3. -Dcom.sun.management.jmxremote.port=监听端口
  4. -Dcom.sun.management.jmxremote.authenticate=false
  5. -Dcom.sun.management.jmxremote.ss1=false
  6. -Djava.rmi.server.hostname=可解析的主机名"
  7. # 具体测试参数如下:
  8. CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote
  9. -Dcom.sun.management.jmxremote.port=11412
  10. -Dcom.sun.management.jmxremote.authenticate=false
  11. -Dcom.sun.management.jmxremote.ss1=false
  12. -Djava.rmi.server.hostname=qfedu.com"
  13. 注意:这里的qfedu.com必须是DNS可解析的主机名,11412为监听端口
  14. 其次在Visua7vM中配置连接到上面配置的服务器加端口的地址上去:
  15. Visua7vM中选择"远程"
  16. 在弹出的窗口中选择"添加远程主机"
  17. 此时会在远程中,多出一台主机。此时点击多出来的主机
  18. 添加连接VM相关的信息