JVM监控及诊断工具-命令行篇

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


01-概述

在这里插入图片描述

简单命令行工具

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

02 jps:查看正在运行的Java进程

基本情况

在这里插入图片描述

测试

我们这里在windows下演示jps的使用
首先打开命令行窗口,输入jps
在这里插入图片描述

public class ScannerTest {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String info = scanner.next();
    }
}

在这里插入图片描述
在这里插入图片描述

本地虚拟机ID和操作系统的进程ID是一致的。
在这里插入图片描述

基本语法

在这里插入图片描述
可以通过 jps -help 来查看对应的参数信息
在这里插入图片描述

options参数

在这里插入图片描述
综合使用:
jps -l -m等价于jps -lm
如何将信息输出到同级文件中:
语法:命令 > 文件名称
例如:jps -l > a.txt

【-q 】
在这里插入图片描述

【-l 】
在这里插入图片描述

【-m】:输出虚拟机进程启动时传递给主类main()的参数

public class ScannerTest {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String info = scanner.next();
    }
}

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

【-v】:列出虚拟机启动时的JVM参数。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

补充:如果某Java进车关闭了默认开启的UsePerfData参数(即使用参数:-XX:-UsePerfData),那么jps命令(以及下面介绍的jstat)将无法探知该java进程。
在这里插入图片描述

在这里插入图片描述

hostid参数

在这里插入图片描述

03-jstat:查看JVM统计信息

基本情况

在这里插入图片描述
在这里插入图片描述

基本语法

在这里插入图片描述
其中vmid是进程id号,也就是jps之后看到的前面的号码,如下:
在这里插入图片描述

option参数

在这里插入图片描述
在这里插入图片描述

public class ScannerTest {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String info = scanner.next();
    }
}

在这里插入图片描述

先以【-class】为例,讲解jstat的用法

在这里插入图片描述

在这里插入图片描述

【interval参数】

用于指定输出统计数据的周期,单位为毫秒。即:查询间隔
在这里插入图片描述
在这里插入图片描述

【count参数】

用于指定查询的总次数
在这里插入图片描述

interval和count只写一个的话,他会认为你是interval

【-t参数】

可以在输出信息前加上一个Timestamp列,显示程序的运行时间。单位:秒
在这里插入图片描述

在这里插入图片描述

【-h参数】

可以在周期性数据输出时,输出多少行数据后输出一个表头信息
在这里插入图片描述

各种option参数的用法

JIT相关的
  • -compiler:显示JIT编译器编译过的方法、耗时等信息。

在这里插入图片描述

  • -printcompilation :输出已经被JIT编译过的方法
  • 在这里插入图片描述
垃圾回收相关的
  • -gc:显示与GC相关的堆信息。包括Eden区、两个Survivor区、老年代、永久代等容量、已用空间、GC时间合计等信息。
    在这里插入图片描述
    在这里插入图片描述

  • -gccapacity:显示内容与-gc基相同,但输出主要关注Java堆各个区域使用的最大、最小空间

  • -gcutils:显示内容与-gc基本相同,但输出主要关注已使用空间占总空间的百分比

  • -gccause:与-gcutil功能相同,但是会额外输出导致最后一次或当前正在发生的GC产生的原因。

  • -gcnew:显示新生代GC状况

  • -gcnewcapacity:显示内容与-gcnew基本相同,但输出主要关注使用到的最大、最小空间

  • -gcold:显示老年代GC状况

  • -gcoldcapacity:显示内容与-gcold基本相同,输出主要关注使用到的最大、最小空间

  • -gcpermcapacity:显示永久代使用到的最大、最小空间

/**
 * @author shkstart
 * @create 17:49
 * -Xms60m -Xmx60m -XX:SurvivorRatio=8
 */
public class GCTest {
    public static void main(String[] args) {
        ArrayList<byte[]> list = new ArrayList<>();

        for (int i = 0; i < 1000; i++) {
            byte[] arr = new byte[1024 * 100];//100KB
            list.add(arr);
            try {
                Thread.sleep(120);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

在这里插入图片描述

在这里插入图片描述

jstat 如何排查OOM和内存泄漏

其实上述代码最终发生OOM
在这里插入图片描述
怎么查看呢?
我们重新启动上述代码
在这里插入图片描述

新启动的进程号为3956可以用 -gcutils监控jvm内存的占比情况:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
我们也可以通过 -gccause打印产生gc的原因
在这里插入图片描述
经验:
在这里插入图片描述
在这里插入图片描述
(0.020-0.004)/(31.6-30.6)

在这里插入图片描述

04-jinfo:实时查看和修改JVM配置参数

基本情况

在这里插入图片描述
在这里插入图片描述

基本语法

查看

  • jinfo -sysprops 进程id :可以查看由System.getProperties()取得的参数
    在这里插入图片描述
  • jinfo -flags 进程id:查看曾经赋过值的一些参数
    在这里插入图片描述
  • jinfo -flag 参数名称 进程id:查看某个java进程的具体参数信息
    在这里插入图片描述

修改

在这里插入图片描述
在这里插入图片描述

  • 针对boolean类型:jinfo -flag [+|-]参数名称 进程id

    如果使用+号,那就可以让该参数起作用,否则使用-号就让该参数不起作用,具体例子如下:

    在这里插入图片描述

  • 针对非boolean类型:jinfo -flag 参数名称=参数值 进程id
    在这里插入图片描述

    修改只对当前进程有效

拓展

  • java -XX:+PrintFlagsInitial:查看所有JVM参数启动的初始值
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • java -XX:+PrintFlagsFinal:查看所有JVM参数的最终值
  • java -参数名称:+PrintCommandLineFlags:查看那些已经被用户或者JVM设置过的详细的XX参数的名称和值

05-jmap:导出内存映像文件&内存使用情况

基本情况

在这里插入图片描述

基本语法

  • -dump:生成Java堆转储快照:dump文件

    特别的:-dump:live只保存堆中的存活对象

  • -heap:输出整个堆空间的详细信息,包括GC的使用、堆配置信息,以及内存的使用信息等.
  • -histo:输出堆中对象的同级信息,包括类、实例数量和合计容量

    特别的:-histo:live只统计堆中的存活对象

  • -permstat:以ClassLoader为统计口径输出永久代的内存状态信息

    仅linux/solaris平台有效

  • -finalizerinfo:显示在F-Queue中等待Finalizer线程执行finalize方法的对象

    仅linux/solaris平台有效

  • -F:当虚拟机进程对-dump选项没有任何响应时,可使用此选项强制执行生成dump文件

    仅linux/solaris平台有效

  • -h | -help:jamp工具使用的帮助命令
  • -J < flag>:传递参数给jmap启动的jvm

使用1:导出内存映像文件

1、手动的方式:

  • jmap -dump:format=b,file=<filename.hprof> < pid>
  • jmap -dump:live,format=b,file=<filename.hprof> < pid>(生产生多使用这种,这个只保存存活的对象,因此较小一些)
/**
 * @author shkstart
 * @create 17:49
 * -Xms60m -Xmx60m -XX:SurvivorRatio=8
 */
public class GCTest {
    public static void main(String[] args) {
        ArrayList<byte[]> list = new ArrayList<>();
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        for (int i = 0; i < 1000; i++) {
            byte[] arr = new byte[1024 * 100];//100KB
            list.add(arr);
            try {
                Thread.sleep(120);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
注意:这个dump文件是二进制文件,因为我电脑安装了Jprofile,所以d盘生成的文件是这样子,它用记事本是打不开的。
在这里插入图片描述
打开是这种乱码。。。
dump文件的打开方式有很多种:jprofile、jconsole、MAT、以及后面说的指令jhat
另外,我们可以看出文件4是比较小的,因为jmap -dump:live,format=b,file=<filename.hprof> < pid>只会保存存活的对象,生产上也建议如此。

2、自动的方式
在这里插入图片描述

手动的方式获取dump文件是随时随意的,但是自动的方式是在系统OOM时生成dump文件

public class GCTest {
    public static void main(String[] args) {
        ArrayList<byte[]> list = new ArrayList<>();
        for (int i = 0; i < 1000; i++) {
            byte[] arr = new byte[1024 * 100];//100KB
            list.add(arr);
            try {
                Thread.sleep(60);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

使用2:显示堆内存相关信息

  • jmap -heap 进程id

    jmap -heap 进程id只是时间点上的堆信息,而jstat后面可以添加参数,可以指定时间动态观察数据改变情况,而图形化界面工具,它们可以用图表的方式动态展示出相关信息,更加直观明了

在这里插入图片描述

Attaching to process ID 12792, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.152-b16

using thread-local object allocation.
Parallel GC with 4 thread(s)

Heap Configuration:
   MinHeapFreeRatio         = 0
   MaxHeapFreeRatio         = 100
   MaxHeapSize              = 62914560 (60.0MB)
   NewSize                  = 20971520 (20.0MB)
   MaxNewSize               = 20971520 (20.0MB)
   OldSize                  = 41943040 (40.0MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 21807104 (20.796875MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 0 (0.0MB)

Heap Usage:
PS Young Generation
Eden Space:
   capacity = 16777216 (16.0MB)
   used     = 2276224 (2.1707763671875MB)
   free     = 14500992 (13.8292236328125MB)
   13.567352294921875% used
From Space:
   capacity = 2097152 (2.0MB)
   used     = 0 (0.0MB)
   free     = 2097152 (2.0MB)
   0.0% used
To Space:
   capacity = 2097152 (2.0MB)
   used     = 0 (0.0MB)
   free     = 2097152 (2.0MB)
   0.0% used
PS Old Generation
   capacity = 41943040 (40.0MB)
   used     = 31980832 (30.499298095703125MB)
   free     = 9962208 (9.500701904296875MB)
   76.24824523925781% used

1766 interned Strings occupying 158112 bytes.
  • jmap -histo 进程id:输出堆中对象的同级信息,包括类、实例数量和合计容量,也是这一时刻的内存中的对象信息
    在这里插入图片描述

使用3:其他作用

这两个指令仅linux/solaris平台有效,所以无法在windows操作平台上演示,并且使用比较小众,不在多说

  • jmap -permstat :查看系统的ClassLoader信息
  • jmap -finalizerinfo:查看堆积在finalizer队列中的对象

小结

在这里插入图片描述

06-jhat:JDK自带堆分析工具(了解)

jhat命令在jdk9及其之后就被移除了,官方建议使用jvisualvm代替jhat,所以该指令只需简单了解一下即可
在这里插入图片描述在这里插入图片描述
其中dumpfile代表dump文件的地址以及名称,例如:
在这里插入图片描述
options参数
在这里插入图片描述
举例如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

07-jstack:打印JVM中线程快照

基本情况

在这里插入图片描述在这里插入图片描述

基本语法

在这里插入图片描述
在这里插入图片描述

public class ThreadDeadLock {

    public static void main(String[] args) {

        StringBuilder s1 = new StringBuilder();
        StringBuilder s2 = new StringBuilder();

        new Thread(){
            @Override
            public void run() {

                synchronized (s1){

                    s1.append("a");
                    s2.append("1");

                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    synchronized (s2){
                        s1.append("b");
                        s2.append("2");

                        System.out.println(s1);
                        System.out.println(s2);
                    }

                }

            }
        }.start();


        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (s2){

                    s1.append("c");
                    s2.append("3");

                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    synchronized (s1){
                        s1.append("d");
                        s2.append("4");

                        System.out.println(s1);
                        System.out.println(s2);
                    }
                }
            }
        }).start();

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
    }


}

在这里插入图片描述

2022-05-07 20:03:01
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.152-b16 mixed mode):

"DestroyJavaVM" #13 prio=5 os_prio=0 tid=0x0000000002ca2800 nid=0x3074 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Thread-1" #12 prio=5 os_prio=0 tid=0x0000000018dc9800 nid=0x2980 waiting for monitor entry [0x0000000019a3f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
	at com.atguigu.jstack.ThreadDeadLock$2.run(ThreadDeadLock.java:63)
	- waiting to lock <0x00000000d60b2630> (a java.lang.StringBuilder)
	- locked <0x00000000d60b2678> (a java.lang.StringBuilder)
	at java.lang.Thread.run(Thread.java:748)

"Thread-0" #11 prio=5 os_prio=0 tid=0x0000000018dc7000 nid=0x3b94 waiting for monitor entry [0x000000001993e000]
   java.lang.Thread.State: BLOCKED (on object monitor)
	at com.atguigu.jstack.ThreadDeadLock$1.run(ThreadDeadLock.java:35)
	- waiting to lock <0x00000000d60b2678> (a java.lang.StringBuilder)
	- locked <0x00000000d60b2630> (a java.lang.StringBuilder)

"Service Thread" #10 daemon prio=9 os_prio=0 tid=0x0000000018cd6000 nid=0x3dc4 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C1 CompilerThread2" #9 daemon prio=9 os_prio=2 tid=0x0000000018cd3000 nid=0x3048 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread1" #8 daemon prio=9 os_prio=2 tid=0x0000000018c84000 nid=0x44bc waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread0" #7 daemon prio=9 os_prio=2 tid=0x0000000018c74000 nid=0x4080 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Monitor Ctrl-Break" #6 daemon prio=5 os_prio=0 tid=0x0000000018c71000 nid=0x47ac runnable [0x000000001933f000]
   java.lang.Thread.State: RUNNABLE
	at java.net.SocketInputStream.socketRead0(Native Method)
	at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
	at java.net.SocketInputStream.read(SocketInputStream.java:171)
	at java.net.SocketInputStream.read(SocketInputStream.java:141)
	at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
	at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
	at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
	- locked <0x00000000d6136878> (a java.io.InputStreamReader)
	at java.io.InputStreamReader.read(InputStreamReader.java:184)
	at java.io.BufferedReader.fill(BufferedReader.java:161)
	at java.io.BufferedReader.readLine(BufferedReader.java:324)
	- locked <0x00000000d6136878> (a java.io.InputStreamReader)
	at java.io.BufferedReader.readLine(BufferedReader.java:389)
	at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:64)

"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x00000000178de800 nid=0x3488 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x0000000018c38800 nid=0x29f8 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x00000000178ba000 nid=0x41c0 in Object.wait() [0x0000000018c2e000]
   java.lang.Thread.State: WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	- waiting on <0x00000000d5f08ec8> (a java.lang.ref.ReferenceQueue$Lock)
	at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
	- locked <0x00000000d5f08ec8> (a java.lang.ref.ReferenceQueue$Lock)
	at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
	at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)

"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x0000000002d92000 nid=0xa64 in Object.wait() [0x0000000018b2f000]
   java.lang.Thread.State: WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	- waiting on <0x00000000d5f06b68> (a java.lang.ref.Reference$Lock)
	at java.lang.Object.wait(Object.java:502)
	at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
	- locked <0x00000000d5f06b68> (a java.lang.ref.Reference$Lock)
	at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)

"VM Thread" os_prio=2 tid=0x0000000017898000 nid=0x44fc runnable 

"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x0000000002cb8000 nid=0x370c runnable 

"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x0000000002cb9800 nid=0x2134 runnable 

"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x0000000002cbb800 nid=0x1184 runnable 

"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x0000000002cbd000 nid=0x4028 runnable 

"VM Periodic Task Thread" os_prio=2 tid=0x0000000018d5a000 nid=0x4750 waiting on condition 

JNI global references: 30


Found one Java-level deadlock:
=============================
"Thread-1":
  waiting to lock monitor 0x0000000018dcfb28 (object 0x00000000d60b2630, a java.lang.StringBuilder),
  which is held by "Thread-0"
"Thread-0":
  waiting to lock monitor 0x0000000018dd5338 (object 0x00000000d60b2678, a java.lang.StringBuilder),
  which is held by "Thread-1"

Java stack information for the threads listed above:
===================================================
"Thread-1":
	at com.atguigu.jstack.ThreadDeadLock$2.run(ThreadDeadLock.java:63)
	- waiting to lock <0x00000000d60b2630> (a java.lang.StringBuilder)
	- locked <0x00000000d60b2678> (a java.lang.StringBuilder)
	at java.lang.Thread.run(Thread.java:748)
"Thread-0":
	at com.atguigu.jstack.ThreadDeadLock$1.run(ThreadDeadLock.java:35)
	- waiting to lock <0x00000000d60b2678> (a java.lang.StringBuilder)
	- locked <0x00000000d60b2630> (a java.lang.StringBuilder)

Found 1 deadlock.


在这里插入图片描述

如果程序中出现死锁问题,jstack就会提示我们,并指出代码行数。

public class TreadSleepTest {
    public static void main(String[] args) {
        System.out.println("hello - 1");
        try {
            Thread.sleep(1000 * 60 * 10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("hello - 2");
    }
}

同样用jstack分析;
在这里插入图片描述

参数

在这里插入图片描述

补充

其实我们也可以自己在代码中追踪线程的路径,用代码进行监控线程

public class TreadSleepTest {
    public static void main(String[] args) {
        System.out.println("hello - 1");
        try {
            Thread.sleep(1000 * 60 * 10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("hello - 2");
    }
}
package com.atguigu.jstack;

import java.util.Map;
import java.util.Set;

/**
 * 演示线程的死锁问题
 *
 * @author shkstart
 * @create 下午 3:20
 */
public class ThreadDeadLock {

    public static void main(String[] args) {

        StringBuilder s1 = new StringBuilder();
        StringBuilder s2 = new StringBuilder();

        new Thread(){
            @Override
            public void run() {

                synchronized (s1){

                    s1.append("a");
                    s2.append("1");

                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    synchronized (s2){
                        s1.append("b");
                        s2.append("2");

                        System.out.println(s1);
                        System.out.println(s2);
                    }

                }

            }
        }.start();


        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (s2){

                    s1.append("c");
                    s2.append("3");

                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    synchronized (s1){
                        s1.append("d");
                        s2.append("4");

                        System.out.println(s1);
                        System.out.println(s2);
                    }
                }
            }
        }).start();

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(new Runnable() {
            @Override
            public void run() {
                Map<Thread, StackTraceElement[]> all = Thread.getAllStackTraces();//追踪当前进程中的所有的线程
                Set<Map.Entry<Thread, StackTraceElement[]>> entries = all.entrySet();
                for(Map.Entry<Thread, StackTraceElement[]> en : entries){
                    Thread t = en.getKey();
                    StackTraceElement[] v = en.getValue();
                    System.out.println("【Thread name is :" + t.getName() + "】");
                    for(StackTraceElement s : v){
                        System.out.println("\t" + s.toString());
                    }
                }
            }
        }).start();
    }


}

"C:\Program Files\JAVA\jdk1.8.0_152\bin\java.exe" "-javaagent:D:\BaiduNetdiskDownload\IntelliJ IDEA 2018.2.2\lib\idea_rt.jar=60020:D:\BaiduNetdiskDownload\IntelliJ IDEA 2018.2.2\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\charsets.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\deploy.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\ext\access-bridge-64.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\ext\cldrdata.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\ext\dnsns.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\ext\jaccess.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\ext\jfxrt.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\ext\localedata.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\ext\nashorn.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\ext\sunec.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\ext\sunjce_provider.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\ext\sunmscapi.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\ext\sunpkcs11.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\ext\zipfs.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\javaws.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\jce.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\jfr.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\jfxswt.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\jsse.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\management-agent.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\plugin.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\resources.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\rt.jar;D:\idea\JVMDemo2\out\production\chapter02" com.atguigu.jstack.ThreadDeadLockThread name is :Thread-2java.lang.Thread.dumpThreads(Native Method)
	java.lang.Thread.getAllStackTraces(Thread.java:1610)
	com.atguigu.jstack.ThreadDeadLock$3.run(ThreadDeadLock.java:82)
	java.lang.Thread.run(Thread.java:748)Thread name is :Monitor Ctrl-Breakjava.net.SocketInputStream.socketRead0(Native Method)
	java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
	java.net.SocketInputStream.read(SocketInputStream.java:171)
	java.net.SocketInputStream.read(SocketInputStream.java:141)
	sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
	sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
	sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
	java.io.InputStreamReader.read(InputStreamReader.java:184)
	java.io.BufferedReader.fill(BufferedReader.java:161)
	java.io.BufferedReader.readLine(BufferedReader.java:324)
	java.io.BufferedReader.readLine(BufferedReader.java:389)
	com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:64)Thread name is :Attach Listener】
【Thread name is :DestroyJavaVM】
【Thread name is :Thread-0com.atguigu.jstack.ThreadDeadLock$1.run(ThreadDeadLock.java:35)Thread name is :Finalizerjava.lang.Object.wait(Native Method)
	java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
	java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
	java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)Thread name is :Reference Handlerjava.lang.Object.wait(Native Method)
	java.lang.Object.wait(Object.java:502)
	java.lang.ref.Reference.tryHandlePending(Reference.java:191)
	java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)Thread name is :Signal Dispatcher】
【Thread name is :Thread-1com.atguigu.jstack.ThreadDeadLock$2.run(ThreadDeadLock.java:63)
	java.lang.Thread.run(Thread.java:748)

在这里插入图片描述

08-jcmd:多功能命令行

基本情况

在这里插入图片描述

基本语法

  • jcmd -l : 列出所有的JVM进程

  • jcmd 进程号 help:针对指定的进程,列出支持的所有具体命令
    在这里插入图片描述

  • jcmd 进程号 具体命令:显示指定进程的指令命令的数据

  • 根据以上命令来替换之前的那些操作:
    Thread.print 可以替换 jstack指令
    GC.class_histogram 可以替换 jmap中的-histo操作
    GC.heap_dump 可以替换 jmap中的-dump操作
    GC.run 可以查看GC的执行情况
    VM.uptime 可以查看程序的总执行时间,可以替换jstat指令中的-t操作
    VM.system_properties 可以替换 jinfo -sysprops 进程id
    VM.flags 可以获取JVM的配置参数信息
    在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值