Virtual Machine Series: Basic Tools for Virtual Machine Performance Monitoring

jvm-8

Earlier we learned about the related technologies of virtual machines, and probably have a relatively systematic understanding of virtual machines. Most of the previous ones are theoretical knowledge, and some will be mixed with some practical operations, but the actual problems encountered are far from enough. Let's practice through the official JDK tools. The accurate use of tools improves our positioning and the efficiency of solving problems.

1. jps: virtual machine process status tool

jps (JVM Process Status Tool) is a tool for the status of the virtual machine process. It can list the virtual machine processes that the virtual machine is running, and is like the name of the virtual machine execution main class (Main Class, the class where the main() function is located) and these The process's local virtual machine unique ID (LVMID, Local Virtual Machine Identifier). This command is definitely the most frequently used JDK command line tool (because most other JDK tools need to enter the LVMID it queries to determine which virtual machine process to monitor).

For the local virtual machine process, the LVMID is the same as the process ID (PID, Process Identifier) ​​of the operating system. The LVMID of the virtual machine process can also be queried by using the Windows Task Manager or the UNIX ps command, but if it starts at the same time If there are multiple virtual machine processes and cannot be located according to the process name, then you must rely on the jps command to display the function of the main class to distinguish.

jps command format

jps [ options ] [ hostid ]

Run jps directly without any parameters as follows

ajisun@ajisun-2 /> jps
81746 Launcher
80005 
16153 Jps
555 Check
复制代码

This output shows that there are 4 applications in the current system, of which the third Jps is the command itself (this command is also a Java program in essence).

Jps can also add parameters to control the output (-q, -m, -l,-v).

jps -q

Only output the process ID (LVMID), omitting the name of the main class

ajisun@ajisun-2 /> jps -q
51573
537
复制代码

jps -m

Output the parameters passed to the main class main() function when the virtual machine process starts

ajisun@ajisun-2 /> jps -m
51585 Jps -m
537 Check Point/Mobile Access/CShell.jar
复制代码

jps -l

Output the full name of the main class, if the process executes a jar package, output the jar path

ajisun@ajisun-2 /> jps -l
51639 sun.tools.jps.Jps
537 /Users/ajisun/Library/Check
复制代码

jps -v

Output the parameters of the JVM when the virtual machine process starts

ajisun@ajisun-2 /> jps -v
51749 sun.tools.jps.Jps -l -m -v -Denv.class.path=.:/Library/Java/JavaVirtualMachines/jdk1.8.0_161.jdk/Contents/Home/lib/dt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_161.jdk/Contents/Home/lib/tools.jar -Dapplication.home=/Library/Java/JavaVirtualMachines/jdk1.8.0_161.jdk/Contents/Home -Xms8m
537 /Users/ajisun/Library/Check Point/Mobile Access/CShell.jar
复制代码

2.jinfo: Java configuration information tool

jinfo(Configuration Info for Java) 的作用是实时查看和调整虚拟机各项参数。

基本语法

jinfo [option] {pid}

其中option的可以为

  • -flag {name}打印指定Java虚拟机的参数值。
  • -flag [+|-]{name} 设置指定Java虚拟机参数的布尔值。(+代表true,-代表false)
  • -flag {name}={value} 设置指定Java虚拟机的参数值

例如打印新生代晋升老年代的年龄

ajisun@ajisun-2 /> jinfo -flag MaxTenuringThreshold 11825
-XX:MaxTenuringThreshold=15
复制代码

例如显示是否打印GC信息

ajisun@ajisun-2 /> jinfo -flag PrintGC 12046
-XX:-PrintGC
复制代码

除了上面的查找参数外,还支持设置参数(不是所有的参数都支持这种设置)

手动打开gc日志的参数可以动态开启或者关闭

ajisun@ajisun-2 /> jinfo -flag PrintGC 12190  // 查看参数 未设置
-XX:-PrintGC
ajisun@ajisun-2 /> jinfo -flag +PrintGC 12190  //设置参数
ajisun@ajisun-2 /> jinfo -flag PrintGC 12190   // 查看参数已设置
-XX:+PrintGC
复制代码

3. jmap: Java内存映射工具

jmap(Memory Map for Java) 命令用于生成堆转储快照(一般称为heapdump或dump文件)。jmap的作用并不仅仅是为了获取堆转储快照,它还可以查询finalize执行队列、Java堆和方法区的 详细信息,如空间使用率、当前用的是哪种收集器等。

基本语法

jmap [option] {pid}

其中option可以为

  • -dump:生成java堆转储快照,格式为:-dump:[live,]format=b,file={filename},其中live子参数说明是否只dump出存活对象。
  • -finalizerinfo:显示在F-Queue中等待Finalizer线程执行finalize方法的对象,只在linux/solaris平台下有效。
  • -heap:显示堆详细信息,如使用哪种回收期、参数配置、分带状况等,只在linux/solaris平台下有效。
  • -histo:显示堆中对象统计信息,包括类、实例数量和合计容量。
  • -clstats:以ClassLoader为统计口径显示永久代内存状况,只在linux/solaris平台下有效。
  • -F:当虚拟机进程对-dump选项没有响应时,可以使用这个选项强制生成dump快照,只在linux/solaris平台下有效。

dump导出应用程序的快照

ajisun@ajisun-2 /> jmap -dump:format=b,file=/Users/ajisun/Desktop/jvmTest/s.txt 13157
Dumping heap to /Users/ajisun/Desktop/jvmTest/s.txt ...
Heap dump file created
复制代码

可以用jhat或者其他工具分析此快照。

4. jhat: 分析Java应用程序的堆快照内容

jhat(JVM Heap Analysis Tool) 命令是jdk提供的与jmap搭配使用,来分析jmap生成的堆转储快照。

如上文dump的文件

ajisun@ajisun-2 /> jhat /Users/ajisun/Desktop/jvmTest/s.txt
Reading from /Users/ajisun/Desktop/jvmTest/s.txt...
Dump file created Tue Jan 04 15:05:15 CST 2022
Snapshot read, resolving...
Resolving 19265 objects...
Chasing references, expect 3 dots...
Eliminating duplicate references...
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.
复制代码

上面输出是分析后的内容,还可以在浏览器中查看,访问http://localhost:7000

如图显示的信息是一个链接,分析内存泄露问题主要会用到“Show heap histogram” 和“OQL”,前者可以找到内存中总容量最大的对象,后者是标准的对象查询语言,使用类似于SQL的语法对内存对象进行查询统计(点击下图中的OQL Help 可以查看其语法)

号外:一般不会用直接使用jhat来分析快照,一是分析快照需要占用较多服务器资源,二是这个分析的比较简单 还有更好的分析工具可用,如VisualVM。

5. jstack: Java堆栈跟踪工具

jstack(Stack Trace for Java) 命令用于生成虚拟机当前时刻的线程快照(一般称为threaddump或者 javacore文件)。线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的目的通常是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间挂起等,都是导致线程长时间停顿的常见原因。线程出现停顿时通过jstack来查看各个线程的调用堆栈,就可以获知没有响应的线程到底在后台做些什么事情,或者等待着什么资源。

基本语法

jstack [ option ] {pid}

其中option可以为

  • -F: 当正常输出的请求不被响应时,强制输出线程堆栈。
  • -l: 除堆栈外,显示关于锁的信息。

例如

**ajisun@ajisun-2 /> jstack -l 12190**

2022-01-04 19:48:41

Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.161-b12 mixed mode):

"Attach Listener" #11 daemon prio=9 os_prio=31 tid=0x00007f8f358db800 nid=0x3407 waiting on condition [0x0000000000000000]

java.lang.Thread.State: RUNNABLE

"Service Thread" #10 daemon prio=9 os_prio=31 tid=0x00007f8f360a8800 nid=0x4003 runnable [0x0000000000000000]

java.lang.Thread.State: RUNNABLE

.......
复制代码

演示下while死循环信息查看

public class Test {
    public static void main(String[] args) {
        while (true){
        }
    }
}
复制代码
ajisun@ajisun-2 /> jps -l

24513 com.ajisun.coding.ajisunmybatis.Test

ajisun@ajisun-2 /> jstack -l 24513
复制代码

上图中可以看到线程处于RUNNABLE状态, 在com.ajisun.coding.ajisunmybatis.Test.main方法的15行出现死循环 。出现死循环,等待,死锁等线程都可以看出具体出现的位置。

死锁的案例

-- 代码如下
public class Test {
    private static Object objectA = new Object();
    private static Object objectB = new Object();

    public static void main(String[] args) {
        new Thread(() -> {
            synchronized (objectA) {
                System.out.println("获取锁objectA");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (objectB) {
                    System.out.println("获取锁objectB");
                }
            }
        }).start();

        new Thread(() -> {
            synchronized (objectB) {
                System.out.println("获取锁objectB");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (objectA) {
                    System.out.println("获取锁objectA");
                }
            }
        }).start();
    }
}
复制代码

开始使用jstack命令,先通过jps找到这个类的pid

ajisun@ajisun-2 /> jps -l
25537 com.ajisun.coding.ajisunmybatis.Test
ajisun@ajisun-2 /> jstack -l 25537
复制代码

如上图,根据输出的信息就能确定死锁的位置。以及出现死锁的两个线程互相持有对象以及等待的对象。

号外:jstack不仅可以得到线程的堆栈信息,还能看出是否死锁以及死锁的具体信息。

6. jcmd:多功能命令行

jcmd(Java Command) 虚拟机诊断命令工具,一个多功能的命令,可以导出堆,查看java进程,导出线程信息,执行GC等,从jdk1.7开始提供。

查看当前系统中的虚拟机

ajisun@ajisun-2 /> jcmd -l
36372 com.ajisun.coding.ajisunmybatis.Allocation
36425 sun.tools.jcmd.JCmd -l
11423 
复制代码

查看虚拟机36372支持的命令

ajisun@ajisun-2 /> jcmd 36372 help
36372:
The following commands are available:
JFR.stop
JFR.start
JFR.dump
JFR.check
VM.native_memory
VM.check_commercial_features
VM.unlock_commercial_features
ManagementAgent.stop
ManagementAgent.start_local
ManagementAgent.start
GC.rotate_log
Thread.print
GC.class_stats
GC.class_histogram
GC.heap_dump
GC.run_finalization
GC.run
VM.uptime
VM.flags
VM.system_properties
VM.command_line
VM.version
help
复制代码

上面输出就是此虚拟机支持的命令

  • 查看虚拟机启动的时间

    ajisun@ajisun-2 /> jcmd 36372 VM.uptime
    36372:
    292.741 s
    复制代码
  • 输出线程栈信息(和jstack命令输出相同)

    ajisun@ajisun-2 /> jcmd 36372 Thread.print
    ......
    "main" #1 prio=5 os_prio=31 tid=0x00007f8729808800 nid=0xe03 runnable [0x0000700002b67000]
       java.lang.Thread.State: RUNNABLE
      at com.ajisun.coding.ajisunmybatis.Allocation.main(Allocation.java:39)
    ​
    "VM Thread" os_prio=31 tid=0x00007f872a816800 nid=0x5003 runnable 
    ......
    复制代码
  • 导出堆信息(和jmap命令功能相同)

    ajisun@ajisun-2 /> jcmd 36372 GC.heap_dump /Users/ajisun/Desktop/jvmTest/jcmd.txt
    36372:
    Heap dump file created
    复制代码

jcmd 36372 help 命令可以看出,jcmd有很多功能,包括覆盖常用的jmap的功能,而且官方也是推荐使用jcmd替换jmap。

7. jstat:虚拟机统计信息工具

用于监视虚拟机各种运行状态信息的命令工具,是比较强大的,可以用来查看堆信息的详细情况。

由于这个命令篇幅较多,在下一篇文章中详细介绍


说明:以上这些命令中部分会出现错误提示

Error attaching to process: sun.jvm.hotspot.debugger.DebuggerException: Can't attach symbolicator to the process

如果使用的mac电脑,没啥办法,但是在Linux上开启ptrace_scope就没问题的,具体的可以网上搜索下。

原文地址


I am Mr. Ji. I use the output to force the input to continue to learn. I continue to share technical series of articles, and the whole network is worth collecting good articles. Welcome to pay attention to the public account and be a technical person who continues to grow.

personal website

JVM virtual machine series of historical articles

1. Virtual machine series: how to generate heap memory when JVM is running;

2. Virtual machine series: garbage collection algorithm in jvm;

3. Virtual machine series: jvm runtime data area;

4. Virtual machine series: object creation, memory layout and access positioning in JVM;

5. Virtual machine series: garbage collector in JVM;

6. Virtual machine series: memory allocation in JVM;

7. Virtual machine series: understand the logs and log parameters of virtual machines;

Guess you like

Origin juejin.im/post/7078495290394673182