jvm 调优工具

1 示例代码

1.1 示例代码1 元空间OOM

设置启动参数:

-XX:+PrintGCDetails -XX:MetaspaceSize=20m -XX:MaxMetaspaceSize=20m
public class MetaspaceOverFlowTest {

    public static void main(String[] args) throws InterruptedException {

        while (true) {
            Thread.sleep(40);
            Enhancer enhancer = new Enhancer();
            enhancer.setUseCache(false);
            enhancer.setSuperclass(MetaspaceOverFlowTest.class);
            enhancer.setCallback(new MethodInterceptor() {
                @Override
                public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                    return methodProxy.invokeSuper(o, objects);
                }
            })  ;
            Object o = enhancer.create();
//            System.out.println(o);
        }

    }

1.2 示例代码2 堆OOM

设置启动参数

-Xms10m -Xmx10m -XX:+PrintGCDetails
public class HeapOverFlowTest {
    int [] intArr = new int[10];
    public static void main(String[] args) throws InterruptedException {
        List<HeapOverFlowTest> list = new ArrayList<>();
        for(;;) {
            Thread.sleep(1);
            list.add(new HeapOverFlowTest());
        }
    }
}

1.3 示例代码3 虚拟机栈OOM

启动参数设置:

-Xss200k```

```java
public class StackOverFlowTest {
    private int i =0;
    public void test() {
        i++;
        test();
    }
    public static void main(String[] args) {
        StackOverFlowTest stackOverFlowTest = new StackOverFlowTest();
        try {
            stackOverFlowTest.test();
        }catch (Throwable e) {
            e.printStackTrace();
            System.out.println(stackOverFlowTest.i);
        }
    }
}

1.4 示例代码4

public class UtilDemo1 {

    public static void main(String[] args) {


        while (true);

    }
}

1.5 示例代码5 死锁

public class DeadLockDemo {
    public static String lockA = "Lock A";
    public static String lockB = "Lock B";

    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lockA) {
                    System.out.println(Thread.currentThread().getName()+"获取到 Lock A 的锁");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"等待 Lock B 的锁。。。");
                    synchronized (lockB) {
                        System.out.println(Thread.currentThread().getName()+"获取到 Lock B 的锁");
                    }
                }
            }
        },"线程A").start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lockB) {
                    System.out.println(Thread.currentThread().getName()+"获取到 Lock B 的锁");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"等待 Lock A 的锁。。。");
                    synchronized (lockA) {
                        System.out.println(Thread.currentThread().getName()+"获取到 Lock A 的锁");
                    }
                }
            }
        },"线程B").start();

    }
}

2 调优工具使用及原理

2.1 PerfData文件

jvm 启动的时候会创建PerfData文件,记录一些数据。Windows下默认路径是C:\Users\username\AppData\Local\Temp\hsperfdata_username,Linux下默认路径是/tmp/hsperfdata_username。

2.1.1 文件创建

取决于两个参数
-XX:-/+UsePerfData
默认是开启的
关闭方式:-XX:-UsePerfData。如果关闭了,就不会创建PerfData文件
-XX:-/+PerfDisableSharedMem(禁用共享内存)
默认是关闭的,即支持内存共享。如果禁用了,依赖于PerfData文件的工具就无法正常工作了

2.1.2 文件删除

默认情况下随Java进程的结束而销毁,但是如kill -9,这种信号jvm是不能捕获的,所以导致进程直接退出了,而没有做一些收尾性的工作,这个时候你会发现进程虽然没了,但是这个文件其实还是存在的;jvm里考虑到了这种情况,会在当前用户接下来的任何一个java进程(比如说我们执行jps)起来的时候会去做一个判断,看/tmp/hsperfdata_下的进程是不是还存在,如果不存在了就直接删除该文件,判断是否存在的具体操作其实就是发一个kill -0的信号看是否有异常。

2.1.3 文件更新

-XX:PerfDataSamplingInterval = 50ms
即内存与PerfData文件的数据延迟为50ms

2.2 jps

jps -q   只显示java进程的ID
jps -l  输出Java进程的ID + main函数所在类的全限定名(包名 + 类名)
jps -m  输出Java进程的ID + main函数所在类的名词 + 传递给main函数的参数
jps -v  输出Java进程的ID + main函数所在类的名称 + 传递给JVM的参数

2.2.1 原理

源码路径:

tools.jar\sun\tools\jps\

JPS的原理是读取取PerfData文件获取信息。

2.2.2 实战

2.2.2.1 jps -q

直接运行示例代码1,使用命令
在这里插入图片描述
输出了所有java进程的ID

2.2.2.2 jps -l

在这里插入图片描述
输出java进程ID+main函数所在类的全限定名。

2.2.2.3 jps -m

运行示例代码1,并给main函数添加参数
在这里插入图片描述
在这里插入图片描述
输出 java进程ID +main函数所在类名称+main函数的参数

2.2.2.4 jps -v

运行示例代码1,并给添加jvm参数
在这里插入图片描述
在这里插入图片描述
输出java进程ID + main函数所在类名称 + jvm 参数。

2.2.2.5 组合使用 jps -lv

在这里插入图片描述
输出java进程ID + main函数所在类全限定名 + jvm 参数。

2.3 jstat

jstat命令可以查看堆内存各部分的使用量,以及加载类的数量。

2.3.1 原理

源码路径:

tools.jar\sun\tools\jstat\

jstat 输出的每一列定义在tools.jar\sun\tools\jstat\resources\jstat_options文件中。
在这里插入图片描述
文件内容如上图,定义了用途和计算方式,其中如java.cls.loadedClasses这类变量是读取的PerfData文件里的内容。

2.3.2 实战

jstat [-命令选项] [vmid] [间隔时间/毫秒] [查询次数]
2.3.2.1 jstat -options

获取所有的命令参数
在这里插入图片描述

2.3.2.2 jstat -class PID

输出类加载信息。
运行实例代码1
在这里插入图片描述
使用jps查出进程ID,然后使用jstat -class 进程ID,查询类加载信息。
各列信息为:

Loaded   装载的类的数量
Bytes    装载类所占用的字节数
Unloaded 卸载类的数量
Bytes    卸载类的字节数
Time     装载和卸载类所花费的时间

jstat 命令还可设置间隔输出,输出几次,比如
在这里插入图片描述
上图为每2秒输出一次,共输出5次。

2.3.2.3 jstat -compiler PID

输出JVM即时编译的信息。
运行示例代码4
在这里插入图片描述
各列信息:

Compiled     编译任务执行数量
Failed       编译任务执行失败数量
Invalid      编译任务执行失效数量
Time         编译任务消耗时间
FailedType   最后一个编译失败任务的类型
FailedMethod 最后一个编译失败任务所在的类及方法
2.3.2.4 jstat -gc PID

输出gc的信息,查看gc的次数,及时间。
运行示例代码1
在这里插入图片描述
各列信息:

S0C   年轻代survivor1的容量 
S1C   年轻代urvivor2的容量 
S0U   年轻代survivor1目前已使用空间 
S1U   年轻代survivor2目前已使用空间
EC    年轻代Eden的容量 
EU    年轻代Eden目前已使用空间 
OC    老年代的容量 
OU    Old代目前已使用空间 
MC	  元空间容量
MU    元空间目前已使用空间
CCSC  压缩类空间大小
CCSU  压缩类空间使用大小
YGC   从应用程序启动到采样时年轻代中gc次数
YGCT  从应用程序启动到采样时年轻代中gc所用时间
FGC   从应用程序启动到采样时full gc次数
FGCT  从应用程序启动到采样时full gc所用时间
GCT   从应用程序启动到采样时gc用的总时间
2.3.2.5 jstat -gccapacity PID

输出年轻代、老年代、元空间信息
运行示例代码1
在这里插入图片描述
各列信息:

NGCMN   年轻代初始化大小
NGCMX   年轻代最大容量 
NGC     年轻代当前的容量 
S0C     survivor1的容量
S1C     survivor2的容量
EC      Eden的容量
OGCMN   老年代中初始化大小
OGCMX   老年代的最大容量
OGC     老年代当前容量 
OC      老年代当前容量
MCMN    元空间最小容量
MCMX    元空间最大容量
MC      当前元空间大小
CCSMN   最小压缩类空间大小
CCSMX   最大压缩类空间大小
CCSC    当前压缩类空间大小
YGC     从应用程序启动到采样时年轻代中gc次数
FGC     从应用程序启动到采样时full gc次数
2.3.2.6 jstat -gccause PID

输出最近一次gc统计和原因
运行示例代码1
在这里插入图片描述
各列信息:

// 使用率 = (已使用/总容量)*100%
S0    survivor1使用率
S1    survivor2使用率
E     Eden使用率
O     老年代使用率
M     元空间使用率 
CCS   压缩类空间使用率
YGC   从应用程序启动到采样时年轻代中gc次数
YGCT  从应用程序启动到采样时年轻代中gc所用时间
FGC   从应用程序启动到采样时full gc次数
FGCT  从应用程序启动到采样时full gc所用时间
GCT   从应用程序启动到采样时gc用的总时间
LGCC  最后一次GC原因
GCC   当前GC原因
2.4.2.7 jstat -gcmetacapacity PID

输出元空间信息
运行示例代码1
在这里插入图片描述
各列信息:

MCMN  元空间初始容量
MCMX  元空间最大容量
MC    当前元空间容量
CCSMN 压缩类空间初始容量
CCSMX 压缩类元空间最大容量
CCSC  当前压缩类容量
YGC   从应用程序启动到采样时年轻代中gc次数
FGC   从应用程序启动到采样时full gc次数
FGCT  从应用程序启动到采样时full gc所用时间
GCT   从应用程序启动到采样时gc用的总时间
2.3.2.8 jstat -gcnew PID

年轻代信息
运行示例代码1
在这里插入图片描述
各列信息:

S0C  survivor1的容量
S1C  survivor2的容量 
S0U  survivor1目前已使用空间
S1U  survivor2目前已使用空间
TT   持有次数限制
MTT  最大持有次数限制
EC   Eden的容量
EU   Eden目前已使用空间
YGC  从应用程序启动到采样时年轻代中gc次数
YGCT 从应用程序启动到采样时年轻代中gc所用时间
2.3.2.9 jstat -gcnewcapacity PID

输出年轻代容量信息
运行示例代码2
在这里插入图片描述

NGCMN   年轻代初始化容量
NGCMX   年轻代的最大容量 
NGC     年轻代当前的容量
S0CMX   survivor1的最大容量
S0C     survivor1当前的容量
S1CMX   survivor2的最大容量
S1C     survivor2当前的容量
ECMX    Eden的最大容量 
EC      Eden的当前容量
YGC     从应用程序启动到采样时年轻代中gc次数
FGC     从应用程序启动到采样时full gc次数
2.3.2.10 jstat -gcold

输出老年代信息
运行示例代码2
在这里插入图片描述
各列信息:

MC   元空间容量
MU   元空间使用容量
CCSC 压缩类空间容量
CCSU 压缩类空间使用容量
OC   老年代的容量
OU   老年代目前已使用容量
YGC  从应用程序启动到采样时年轻代中gc次数
FGC  从应用程序启动到采样时full gc次数
FGCT 从应用程序启动到采样时full gc所用时间
GCT  从应用程序启动到采样时gc用的总时间
2.3.2.11 jstat -gcoldcapacity PID

输出老年代容量信息
运行实例代码2
在这里插入图片描述
各列信息:

OGCMN  老年代初始化容量
OGCMX  老年代的最大容量
OGC    老年代当前容量
OC     老年代的容量
YGC    从应用程序启动到采样时年轻代中gc次数
FGC    从应用程序启动到采样时full gc次数
FGCT   从应用程序启动到采样时full gc所用时间
GCT    从应用程序启动到采样时gc用的总时间
2.3.2.12 jstat -gcutil PID

输出gc统计信息
运行示例代码2
在这里插入图片描述

各列信息:

// 使用率 = (已使用/总容量)*100%
S0    survivor1使用率
S1    survivor2使用率
E     Eden使用率
O     老年代使用率
M     元空间使用率 
CCS   压缩类空间使用率
YGC   从应用程序启动到采样时年轻代中gc次数
YGCT  从应用程序启动到采样时年轻代中gc所用时间
FGC   从应用程序启动到采样时full gc次数
FGCT  从应用程序启动到采样时full gc所用时间
GCT   从应用程序启动到采样时gc用的总时间
2.3.2.13 jstat -printcompilation PID

输出当前jvm执行信息
运行示例代码2
在这里插入图片描述
各列信息:

Compiled 编译任务的数量
Size     方法生成的字节码的大小
Type     编译类型
Method   类名和方法名用来标识编译的方法。类名使用/做为一个命名空间分隔符。方法名是给定类中的方法。上述格式是由-XX:+PrintComplation选项进行设置的

2.4 jstack

打印给定java进程ID的堆栈信息,即java虚拟机当前时刻的线程快照,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等。
源码路径:

tools.jar\sun\tools\jstack\

2.4.1 实战

-l  除堆栈外,打印额外的锁信息,发生死锁用这个来观察。
-F  正常输出的请求未响应时,强制输出线程堆栈。
-m  如果调用到本地方法的话,可以打印C/C++的堆栈
-h 帮助信息
2.4.1.1 jstack -l PID

运行示例代码5
在这里插入图片描述
上图为jstack 输出的部分信息,可以看出:
线程A锁住了0x00000000d5ef58d0在等待0x00000000d5ef5908
线程B锁住了0x00000000d5ef5908在等待0x00000000d5ef58d0
在这里插入图片描述
上图为jstack 输出部分信息,可以已看出:已经明确是输出发现了一个java级别的死锁。

2.3.1.2 jstack -F PID

正常输出的请求未响应时,使用这个命令强制输出。

2.3.1.3 jstack -m PID

调用到本地方法的话,可以打印C/C++的堆栈。

2.5 jinfo

用于打印配置信息,包括命令行参数、系统变量。极少数的情况下,我们可以用其来修改命令行参数。

jinfo -flags PID  查看JVM参数 如-Xms -Dfile.encoding=GBK
jinfo -flags +/- name PID 用于开启或关闭虚拟机标记参数。+表示开启,-表示关闭,有+或-表示设置,没有+或-就是打印参数。如jinfo -flags +PrintGC PID
jinfo -flags name=value PID 设置虚拟机参数 ,并不是每个参数都可以设置。如:jinfo -flags HeapDumpPath PID 设置dump日志路径
jinfo -sysprops PID 查看系统参数 System.getProperty(key);

2.5.1 实战

2.5.1.1 jinfo -flags PID

查看jvm参数
运行示例代码2
设置参数
在这里插入图片描述
在这里插入图片描述

2.5.1.2 jinfo -flags +/- name PID

用于开启或关闭布尔类型虚拟机标记参数。+表示开启,-表示关闭,有+或-表示设置,没有+或-就是打印参数。
以PrintGC为例
运行示例代码2

2.5.1.3 jinfo -flags name=value PID

设置字符串和数字类型虚拟机参数 ,并不是每个参数都可以设置。如:jinfo -flags HeapDumpPath PID 设置dump日志路径。

2.5.1.4 jinfo -sysprops PID

查看系统参数 System.getProperty(key);
运行示例代码2 设置系统参数
在这里插入图片描述
在这里插入图片描述

2.6 jmap

输出所有内存中对象的工具,甚至可以将VM 中的heap,以二进制输出成文本。

jmap -dump:live,fomat=b,file=dump.hprof PID 打印当前dump堆到文件,format指定输出格式,live指明是活着的对象,file指定文件名。文件可用VisualVM打开,可查看类的实例数量和大小。
jmap -heap PID 打印heap的概要信息,GC使用的算法,heap(堆)的配置及JVM堆内存的使用情况。
jmap -finalizerinfo PID 打印正等候回收的对象的信息。
jmap -histo:live PID 打印每个class的实例数目,内存占用,类全名信息. VM的内部类名字开头会加上前缀”*”. 
如果live子参数加上后,只统计活的对象数量. 这个命令执行,jvm会先触发GC,然后再统计信息。
jmap -clstats PID 打印Java类加载器的智能统计信息,对于每个类加载器而言,它的名称,活跃度,地址,父类加载器,它所加载的类的数量和大小都会被打印。此外,包含的字符串数量
和大小也会被打印。-F 强制模式。如果指定的pid没有响应时使用;如:jmap -F -histo 129665

2.6.1 实战

2.6.1.1 jmap -dump:live,fomat=b,file=dump.hprof PID

打印当前dump堆到文件,format指定输出格式,live指明是活着的对象,file指定文件名。文件可用VisualVM打开,可查看类的实例数量和大小。
运行示例代码2
在这里插入图片描述
在jvm-demo1目录下生成了heap.hprof文件
打开jvisual VM
在这里插入图片描述
在这里插入图片描述
点击文件 --> 装入 ,选择刚刚生成的文件。
在这里插入图片描述
首页是一些概要信息,如加载类总数、实例总数。
在这里插入图片描述
点击类这个选项卡可以看出int[]实例数最多,并且所占容量最大,双击这行。
在这里插入图片描述
可以看到大部分引用都是来自HeapOverFlowTest.intArr,所以如果是内存泄漏的话,可以根据这种方式来定位问题。
我们可以在启动jvm的时候添加参数-XX:+HeapDumpOnOutOfMemoryError,再发生Heap的OOM的时候会自动生成堆的dump文件。

2.6.1.2 jmap -heap PID

打印heap的概要信息,GC使用的算法,heap(堆)的配置及JVM堆内存的使用情况。
运行代码示例2
在这里插入图片描述
上图为各部分的容量大小。
在这里插入图片描述
上图为各部分的使用情况。

2.6.1.3 jmap -finalizerinfo PID

打印正等候回收的对象的信息。
在这里插入图片描述
上图可以看出值为0没有要回收的对象。

2.6.1.4 jmap -histo:live PID

打印每个class的实例数目,内存占用,类全名信息. JVM的内部类名字开头会加上前缀”*”。live 表示存活对象。
运行实例代码2
在这里插入图片描述
各列信息:

num        编号id
instances  实例个数
bytes      所有实例大小
class name 类名
2.6.1.5 jmap -clstats PID

打印Java类加载器的智能统计信息,对于每个类加载器而言,它的名称,活跃度,地址,父类加载器,它所加载的类的数量和大小都会被打印。此外,包含的字符串数量
和大小也会被打印。
运行示例代码2
在这里插入图片描述
各列信息

class_loader   类加载器实例
classes        加载类数量
bytes          加载类大小
parent_loader  父类加载器
alive          是否存活
type           类加载器类型
2.6.1.6 -F强制模式

如果指定的pid没有响应时使用;如:jmap -F -histo 129665

2.7 jconsole

jconsole是jdk自带的基于JMX的可视化监视、管理工具。

2.7.1 启动

jconsole 位于 JAVA_HOME/bin/jconsole.exe 目录。

在这里插入图片描述
现在运行示例代码1
在这里插入图片描述
找到你需要监控的进程,连接。
在这里插入图片描述

上图为概览页面,可以看出一共分为概览、内存、线程、类、VM概要、Mbean6各模块。

2.7.2 概览

显示内存使用率,线程数,Java VM中加载的类数量、CPU使用率的监控信息。
在这里插入图片描述

2.7.3 内存

显示了运行时内存各部分的使用信息,如下图可以选择堆、老年代、Eden等。
在这里插入图片描述

2.7.4 线程

显示线程有关信息
运行示例代码5
在这里插入图片描述
如上图显示了线程A锁定了java.lang.String@330ce8a5,现在时状态:BLOCKED,
获取java.lang.String@7af45c69的锁阻塞了, 拥有者: 线程B
点击检查死锁
在这里插入图片描述
可以看到线程A和线程B死锁了。

2.7.5 类

现在类加载信息
在这里插入图片描述

2.7.6 VM 概要

VM概要显示了虚拟机信息,运行时间、编译器、线程、类加载等、classpath、堆、垃圾收集器等等.
在这里插入图片描述

2.7.8 MBean

在这里插入图片描述

2.7.9 远程连接

远程连接,必须配置JMX连接参数。

-Djava.rmi.server.hostname=host  #远程服务器ip,即本机ip
-Dcom.sun.management.jmxremote #允许JMX远程调用
-Dcom.sun.management.jmxremote.port=port  #自定义jmx 端口号
-Dcom.sun.management.jmxremote.ssl=false  # 是否需要ssl 安全连接方式
-Dcom.sun.management.jmxremote.authenticate=false #是否使用用户名和密码验证,此处也选择false

再启动jvm时加入以上参数;
在这里插入图片描述

tomcat的配置是在catalina.sh文件里的最后一个JAVA_OPTS的赋值语句下一行增加一行
JAVA_OPTS="$JAVA_OPTS ‐Dcom.sun.management.jmxremote.port=8888 …",把上述的几个配置项都添加进去。

2.8 jvsiualvm

jvsiualvm是jdk自带的监控工具,可以监控内存泄露,跟踪垃圾回收,执行时内存、cpu分析,线程分析等,几乎包含上面介绍的所有监控命令的功能。
位于JAVA_HOME/bin/jvisiualvm.exe
在这里插入图片描述

2.8.1 启动

启动示例代码2
在这里插入图片描述

如果启动了java进程,可以再本地找到java进程。
双击进程
在这里插入图片描述

可以看到有概述、监视、线程、抽样器、Profiler、Visual GC(通过插件自己安装)

2.8.2 概述

可以看到显示了虚拟机信息,和JVM参数 ,系统属性。
在这里插入图片描述

2.8.3 监视

显示了CPU使用率、元空间、堆内存的使用,类加载数量,线程信息。
在这里插入图片描述

点击堆dump ,可以查看堆的快照信息,显示实例数量等信息。
在这里插入图片描述
点击类选项卡
在这里插入图片描述

上图位类选项卡的显示的信息,显示类的实例数量和所占空间大小,双击红框中的类,如下图,显示了实例种的引用信息,和被引用的信息。
在这里插入图片描述

2.8.4 线程

显示线程的名称和运行的状态,也可显示死锁信息,可以点进一个线程查看这个线程的详细运行情况
运行示例代码5
在这里插入图片描述
点击上图的堆dump,可以显示线程详细信息。
在这里插入图片描述

2.8.5 抽样器

显示CPU和内存使用情况
CPU:
在这里插入图片描述
内存:
在这里插入图片描述

2.8.6 Visual GC

显示jvm内存各部分使用情况
在这里插入图片描述

2.8.7 远程连接

远程连接,必须配置JMX连接参数。

-Djava.rmi.server.hostname=host  #远程服务器ip,即本机ip
-Dcom.sun.management.jmxremote #允许JMX远程调用
-Dcom.sun.management.jmxremote.port=port  #自定义jmx 端口号
-Dcom.sun.management.jmxremote.ssl=false  # 是否需要ssl 安全连接方式
-Dcom.sun.management.jmxremote.authenticate=false #是否使用用户名和密码验证,此处也选择false

在这里插入图片描述

填写IP地址点击确定。
在这里插入图片描述

2.8.8 导入堆的dump文件

运行示例代码2,添加参数-XX:+HeapDumpOnOutOfMemoryError,发生堆OOM时候保存堆的快照信息。
在这里插入图片描述
启动后等待OOM后再项目跟目录下找到快照文件
在这里插入图片描述
导入文件,选择文件 --> 装入
在这里插入图片描述
在这里插入图片描述
如何使用查看本篇2.6.1.1章节。

2.9 arthas

Arthas(阿尔萨斯)是阿里巴巴开源的 Java 诊断工具。
下载路径:https://github.com/alibaba/arthas/releases

2.9.1 启动

java -jar arthas-boot.jar
运行示例代码1
在这里插入图片描述
输入前面的序号进入进程
在这里插入图片描述

2.9.2 dashboard

显示当前的线程信息,内存使用情况。
在这里插入图片描述
表格中各列信息说明:

ID          Java级别的线程ID,注意这个ID不能跟jstack中的nativeID一一对应。
NAME        线程名
GROUP       线程组名
PRIORITY    线程优先级, 1~10之间的数字,越大表示优先级越高
STATE       线程的状态
CPU%        线程的cpu使用率。比如采样间隔1000ms,某个线程的增量cpu时间为100ms,则cpu使用率=100/1000=10%
DELTA_TIME  上次采样之后线程运行增量CPU时间,数据格式为秒
TIME        线程运行总CPU时间,数据格式为分:秒
INTERRUPTED 线程当前的中断位状态
DAEMON      是否是daemon线程

线程信息下方是jvm运行时内存各部分使用情况
还可对命令添加参数:

dashboard -i1000 -n3
-i 每多少ms刷新一次
-n一共刷新几次

2.9.3 thread

查看当前线程信息,查看线程的堆栈

thread -n 3  指定最忙的前N个线程并打印堆栈
thread -b 找出当前阻塞其他线程的线程
thread -i 指定cpu使用率统计的采样间隔,单位为毫秒

运行示例代码5
在这里插入图片描述

2.9.3.1 中文乱码解决

上图种可以看到我们线程的中文名字乱码了,需要在启动的时指定字符集
java -jar -Dfile.encoding=UTF-8 arthas-boot.jar
在这里插入图片描述
可以看到中文显示正常。

2.9.3.2 thread id

显示指定id线程的堆栈信息,如打印线程A的堆栈,线程A的ID 为12
在这里插入图片描述

2.9.3.3 thread -b

找出当前阻塞其他线程的线程,目前只支持找出synchronized关键字阻塞住的线程, 如果是java.util.concurrent.Lock, 目前还不支持。
在这里插入图片描述

2.9.3.4 thread -n

当前最忙的前N个线程并打印堆栈
在这里插入图片描述

2.9.3.5 thread -i

指定采样时间间隔,如:
thread -i 1000 : 统计最近1000ms内的线程CPU时间。
thread -n 3 -i 1000 : 列出1000ms内最忙的3个线程栈

2.9.3.6 thread –state

查看指定状态的线程,如
thread -state BLOCKED 查看阻塞状态的线程
在这里插入图片描述

2.9.4 sysprop

查看和修改JVM的系统属性

2.9.4.1 sysprop

查看所有属性
在这里插入图片描述

2.9.4.2 sysprop key

查看单个属性
在这里插入图片描述

2.9.4.3 sysprop key value

修改单个属性
在这里插入图片描述

2.9.5 vmoption

查看,更新VM诊断相关的参数,如打印堆dump,是否打印gc信息,修改堆扩容的空闲堆比例等。

2.9.5.1 vmoption

查看所有的option
在这里插入图片描述

2.9.5.2 vmoption key

查看指定的option
在这里插入图片描述

2.9.5.3 vmoption key value

更新指定的option
在这里插入图片描述

2.9.6 getstataic

查看类的静态属性
使用方法为
getstatic class_name field_name
在这里插入图片描述

2.9.7 ognl

执行ognl表达式
如:
ognl ‘@java.lang.System@out.println(“hello arthas”)’ 调用静态函数,输出在日志中或控制台
在这里插入图片描述
在这里插入图片描述

2.9.8 heapdump

打印当前dump堆到文件,如:
heapdump /tmp/dump.hprof
heapdump --live /tmp/dump.hprof 只要活的对象
在这里插入图片描述
hprof文件的查看,请看上文2.8.8

2.10 HSDB

HSDB(Hotspot Debugger),JDK自带的工具,用于查看JVM运行时的状态。
HSDB位于JAVA_HOME\lib\sa-jdi.jar里面
启动命令:
java -cp .\sa-jdi.jar sun.jvm.hotspot.HSDB
启动后界面如下:
在这里插入图片描述

2.10.1 连接java进程

找到java进程ID
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.10.2 查看线程堆栈信息

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

2.10.3 查看类加载信息

在这里插入图片描述
在这里插入图片描述
显示了jvm加载的所有的类,找到我们自己的类,
在这里插入图片描述

该类元信息实例InstanceKlass实例的内存地址
在这里插入图片描述
在这里插入图片描述
上图输入内存地址,查看类的元信息。

2.10.4 查看堆中的实例

在这里插入图片描述
在这里插入图片描述
上图中显示了各类型的实例数量和实例总大小。

以上仅是目前对这些工具粗浅的使用,以后深入理解后会继续更新完善。

参考连接:
https://blog.csdn.net/shudaqi2010/article/details/53607627
https://blog.csdn.net/zhaozheng7758/article/details/8623549

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值