美文网首页
JVM监控-命令行

JVM监控-命令行

作者: 乙腾 | 来源:发表于2021-06-18 07:03 被阅读0次

jps 看java进程

语法

jps[options] [hostid]

options参数

  • -q :仅仅显示LVMID (local virtual machine id),即本地虚拟机唯一id。不显示主类的名称等

  • -1:输出应用程序主类的全类名或如果进程执行的是jar包,则输出jar完整路径

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

  • -v:列串虚拟机进程启动时的JVM参数。比如: -Xms20m-Xmx50m是启动程序指定的jvm参数。

说明:以上参数可以综合使用。

补充:

如果某Java进程关闭了默认开启的UsePerfData参数(即使用参数-XX:-UsePerfData) ,那么jps命令(以及下面介绍的jstat)将无法探知该Java进程。

jstat 统计监测JVM的gc信息

jstat(JVM Statistics Monitoring Tool): 用户监视虚拟机各种运行状态信息的命令行工具,它可以显示本地或者远程虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行的数据。

常用于检测垃圾回收以及内存泄漏问题。

语法:

jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]

option:行为

vmid:进程id

interval:用于指定输出统计数据的周期,单位为毫秒。即时间间隔。单位:毫秒

count:用于指定查询的总次数。

-t:可以输出信息前加上一个Timestamp列,显示程序运行时间。单位:秒。

-h:可以在周期性数据输出时,输出多少行数据后输出一个表头信息。

options

类装载相关:

  • -class:显示ClassLoader的相关信息:类的装载、卸载数量、总空间、类装载所消耗的时间等

垃圾回收相关的:.

  • -gc:显示与GC相关的堆信息。包括Eden区、两个Survivor区、老年代、永久代等的容量、,用空间、GC时间合计等信息。
  • -gccapacity:显示内容与-gc基本相同,但输出主要关注Java堆各个区域使用到的最大、最小空间。
  • gcutil:显示内容与-gc基本相同,但输出主要关注已使用空间占总空间的百分比。
  • -gccause:与-gcutil功能一样,但是会额外输出导致最后一次或当前正在发生的GC产生的原因。
  • -gcnew:显示新生代GC状况-
  • gcnewcapacity:显示内容与-gcnew基本相同,输出主要关注使用到的最大、最小空间
  • -geold:显示老年代GC状况

重点使用介绍:

jstat -class

                jstat  option vmid  默认 count 为1
root@server:~# jstat -class 8533
Loaded  Bytes  Unloaded  Bytes     Time
  6646 11821.1        0     0.0      12.75
装载个数  字节数     卸载个数   字节数     使用时间

                jstat  option vmid  interval
root@server:~# jstat -class 8533 1000
Loaded  Bytes  Unloaded  Bytes     Time
  6703 11911.1        0     0.0      12.77
  6703 11911.1        0     0.0      12.77
  6703 11911.1        0     0.0      12.77

               jstat  option vmid  interval   count
root@server:~# jstat -class 8533   1000      10
Loaded  Bytes  Unloaded  Bytes     Time
  6703 11911.1        0     0.0      12.77
  6703 11911.1        0     0.0      12.77
  6703 11911.1        0     0.0      12.77
  6703 11911.1        0     0.0      12.77
  6703 11911.1        0     0.0      12.77
  6703 11911.1        0     0.0      12.77
  6703 11911.1        0     0.0      12.77
  6703 11911.1        0     0.0      12.77
  6703 11911.1        0     0.0      12.77
  6703 11911.1        0     0.0      12.77


root@server:~# jstat -class -t 8533
Timestamp       Loaded  Bytes  Unloaded  Bytes     Time
 590.7          6703 11911.1        0     0.0      12.77
程序从开始执行到现在一共多少秒  590.7 s



              jstat  option    -h    vmid  interval   count
root@server:~# jstat -class -t -h3  8533 1000 10
Timestamp       Loaded  Bytes  Unloaded  Bytes     Time
          738.0   6703 11911.1        0     0.0      12.77
          739.0   6703 11911.1        0     0.0      12.77
          740.0   6703 11911.1        0     0.0      12.77
Timestamp       Loaded  Bytes  Unloaded  Bytes     Time
          741.0   6703 11911.1        0     0.0      12.77
          742.0   6703 11911.1        0     0.0      12.77
          743.0   6703 11911.1        0     0.0      12.77
Timestamp       Loaded  Bytes  Unloaded  Bytes     Time
          744.0   6703 11911.1        0     0.0      12.77
          745.0   6703 11911.1        0     0.0      12.77
          746.0   6703 11911.1        0     0.0      12.77
Timestamp       Loaded  Bytes  Unloaded  Bytes     Time
          747.0   6703 11911.1        0     0.0      12.77
-h3 每隔3行输出一次表头

jstat -gc

root@server:~# jstat -gc  8533

 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
10240.0 8192.0  0.0    0.0   249856.0 11848.7   35840.0    13983.8   36048.0 33375.8 4864.0 4371.3      9    1.776   2      0.312    2.088


root@server:~# jstat -gccause  8533 1000 10                                       gc的原因(这里是元空间)
  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT    LGCC                 GCC
  0.00   0.00   4.74  39.02  92.59  89.87      9    1.776     2    0.312    2.088 Metadata GC Threshold No GC
  0.00   0.00   4.74  39.02  92.59  89.87      9    1.776     2    0.312    2.088 Metadata GC Threshold No GC
  0.00   0.00   4.74  39.02  92.59  89.87      9    1.776     2    0.312    2.088 Metadata GC Threshold No GC
  0.00   0.00   4.74  39.02  92.59  89.87      9    1.776     2    0.312    2.088 Metadata GC Threshold No GC
  0.00   0.00   4.74  39.02  92.59  89.87      9    1.776     2    0.312    2.088 Metadata GC Threshold No GC
  0.00   0.00   4.74  39.02  92.59  89.87      9    1.776     2    0.312    2.088 Metadata GC Threshold No GC
  0.00   0.00   4.74  39.02  92.59  89.87      9    1.776     2    0.312    2.088 Metadata GC Threshold No GC
  0.00   0.00   4.74  39.02  92.59  89.87      9    1.776     2    0.312    2.088 Metadata GC Threshold No GC
  0.00   0.00   4.74  39.02  92.59  89.87      9    1.776     2    0.312    2.088 Metadata GC Threshold No GC
  0.00   0.00   4.74  39.02  92.59  89.87      9    1.776     2    0.312    2.088 Metadata GC Threshold No GC

单位:kb

列说明

S0C:第一个幸存区的大小
S1C:第二个幸存区的大小
S0U:第一个幸存区的使用大小
S1U:第二个幸存区的使用大小
EC:伊甸园区的大小
EU:伊甸园区的使用大小
OC:老年代大小
OU:老年代使用大小
MC:方法区大小
MU:方法区使用大小
CCSC:压缩类空间大小
CCSU:压缩类空间使用大小
YGC:年轻代垃圾回收次数
YGCT:年轻代垃圾回收消耗时间
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间   FGC时间+YGC时间

经验

可以通过比较进程的启动时间(Timestamp)和GC时间(GCT列),或者两次测量的间隔时间和总GC时间的增量,来得出GC时间占运行时间的比例。

如果该比例超过20%,则说明目前堆的压力比较大,如果该比例超过90%,则说明堆里几乎没有可用空间,随时都可能抛出OOM异常。

jinfo 实时查看和修改 JVM 配置参数值

jinfo(Configuralion Info for Java) : 查看虚拟机配置参数信息,也可用于调整虚拟机的配置参数。

在很多情况下,Java 应用程序不会指定所有的 Java 虚拟机参数。而此时,开发人员可能不知道某一个具体的 Java 虚拟机参数的默认值。

在这种情况下,可能需要通过查找文档获取某个参数的默认值。这个查找过程可能是非常艰难的。但有了 jinfo 工具,开发人员可以很方便地找到 Java 虚拟机参数的当前值。

基本语法

jinfo [ options ] pid

options

选项 选项说明
no option 输出全部的参数和系统属性
-flag name 输出对应名称的参数
-flag [±]name 开启或者关闭对应名称的参数只有被标记为 manageable 的参数才可以被动态修改
-flag name=value 设定对应名称的参数
-flags 输出全部的参数
-sysprops 输出系统属性

常见用法

查看

jinfo -flags PID

查看曾经赋过值的一些参数

root@server:~# jinfo -flags 9290
JVM version is 25.191-b12
Non-default VM flags:
-XX:CICompilerCount=3 -XX:InitialHeapSize=62914560
-XX:MaxHeapSize=62914560 -XX:MaxNewSize=20971520
-XX:MinHeapDeltaBytes=524288 -XX:NewSize=20971520
-XX:OldSize=41943040 -XX:SurvivorRatio=8 -XX:+UseCompressedClassPointers
-XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps
-XX:-UseLargePagesIndividualAllocation
-XX:+UseParallelGC
Command line:  -Xms60m -Xmx60m -XX:SurvivorRatio=8

jinfo -flag 具体参数 PID

root@server:~# jinfo -flag PrintGCDetails 9290
-XX:-PrintGCDetails

修改

jinfo 不仅可以查看运行时某一个 Java 虚拟机参数的实际取值,甚至可以在运行时修改部分参数,并使之立即生效。

但是,并非所有参数都支持动态修改。参数只有被标记为 manageable 的 flag 可以被实时修改。其实,这个修改能力是极其有限的。

可以查看被标记为 manageable 的参数。

针对 boolean 类型:

jinfo -flag [+-]具体参数 PID
root@server:~# jinfo -flag PrintGCDetails 9290
-XX:-PrintGCDetails
root@server:~# jinfo -flag +PrintGCDetails 9290
-XX:-PrintGCDetails

针对 非boolean 类型:

root@server:~# jinfo -flag MinHeapFreeRatio 9290-XX:MinHeapFreeRatio=0root@server:~# jinfo -flag MinHeapFreeRatio=1 9290root@server:~# jinfo -flag MinHeapFreeRatio 9290-XX:MinHeapFreeRatio=1

补充

java -XX+PrintFlagslnitial PID:查看所有 JVM 参数启动的初始值。
java -XX:+PrintFlagsFinal PID:查看所有 JVM 参数的最终值。
java -XX+PrintCommandLineFlags PID:查看已经被用户或者 JVM 设置过的详细参数名称和值

jmap 导出堆内存快照

jmap(JVM Memory Map) : 作用一方面是获取 dump 文件(堆转储快照文件,二进制文件),它还可以获取目标 Java 进程的内存相关信息,包括 Java堆各区域的使用情况堆中对象的统计信息类加载信息等。

基本语法

jmap [option] <pid>
        (to connect to running process) 连接到正在运行的进程

jmap [option] <executable <core>
    (to connect to a core file)     连接到核心文件

jmap [option] [server_id@]<remote server IP or hostname>
               (to connect to remote debug server) 连接到远程调试服务

>    pid:    目标进程的PID,进程编号,可以采用ps -ef | grep java 查看java进程的PID;
>    executable:     产生core dump的java可执行程序;
>    core:     将被打印信息的core dump文件;
>    remote-hostname-or-IP:     远程debug服务的主机名或ip;
>    server-id:     唯一id,假如一台主机上多个远程debug服务;

options

表头 表头
-dump 生成 dump 文件,-dump:live 只保存堆中存活的对象
-heap 输出整个堆空间的详细信息,包括 GC 的使用、堆配置信息,以及内存的使用信息等
-histo 输出堆空间中对象的统计信息,包括类、实例数量和合计容量
-permstat 以 ClassLoader 为统计口径输出永久代的内存状态信息(仅 linux/solaris 平台有效)
-finalizerinfo 显示在 F-Queue 中等待 Finalizer 线程执行 finalize 方法的对象(仅 linux/solaris 平台有效)
-F 当虚拟机进程对-dump 选项没有任何响应时,强制执行生成 dump 文件(仅 linux/solaris 平台有效)

说明:这些参数和 linux 下输入显示的命令多少会有不同,包括也受 jdk 版本的影响。

常见用法

输出dump文件(Java堆转储快照)

一般来说,使用 jmap 指令生成 dump 文件的操作算得上是最常用的 jmap 命令之一,将堆中所有存活对象导出至一个文件之中。

root@server:~# jmap -dump:live,format=b,file=order1.hprof 19570
root@server:~# ll
drwxr-xr-x  3 root root 4096 5月  26 06:27 order1.hprof

补充说明:

  • Heap Dump 又叫做堆存储文件,指一个<font color=red> Java 进程在某个时间点的内存快照</font>。
  • 通常在<font color=red>写 Heap Dump 文件前会触发一次 Full GC </font>, 所以 Heap Dump 文件里保存的都是 Full GC 后留下的对象信息。
  • 由于生成 dump 文件比较耗时,大家需要耐心等待,尤其是大内存镜像生成的 dump 文件则需要耗费更长的时间来完成。
  • 有些时候,通过命令行输出dump文件会来不及,当程序发生 OOM 退出系统时,一些瞬时信息都随着程序的终止而消失,而重现 OOM 问题往往比较困难或者耗时。这个时候就需要在OOM 时,自动导出 dump 文件。
    • 启动参数:-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=<filename.hprof>

打印heap的概要信息

jmap -heap PID

打印heap的概要信息,GC使用的算法,heap(堆)的配置及JVM堆内存的使用情况

using parallel threads in the new generation.  ##新生代采用的是并行线程处理方式

using thread-local object allocation.   

Concurrent Mark-Sweep GC   ##同步并行垃圾回收

Heap Configuration:  ##堆配置情况,也就是JVM参数配置的结果[平常说的tomcat配置JVM参数,就是在配置这些]
   MinHeapFreeRatio = 40 ##最小堆使用比例
   MaxHeapFreeRatio = 70 ##最大堆可用比例
   MaxHeapSize      = 2147483648 (2048.0MB) ##最大堆空间大小
   NewSize          = 268435456 (256.0MB) ##新生代分配大小
   MaxNewSize       = 268435456 (256.0MB) ##最大可新生代分配大小
   OldSize          = 5439488 (5.1875MB) ##老年代大小
   NewRatio         = 2  ##新生代比例
   SurvivorRatio    = 8 ##新生代与suvivor的比例
   PermSize         = 134217728 (128.0MB) ##perm区 永久代大小
   MaxPermSize      = 134217728 (128.0MB) ##最大可分配perm区 也就是永久代大小

Heap Usage: ##堆使用情况【堆内存实际的使用情况】
New Generation (Eden + 1 Survivor Space):  ##新生代(伊甸区Eden区 + 幸存区survior(1+2)空间)
   capacity = 241631232 (230.4375MB)  ##伊甸区容量
   used     = 77776272 (74.17323303222656MB) ##已经使用大小
   free     = 163854960 (156.26426696777344MB) ##剩余容量
   32.188004570534986% used ##使用比例
Eden Space:  ##伊甸区
   capacity = 214827008 (204.875MB) ##伊甸区容量
   used     = 74442288 (70.99369812011719MB) ##伊甸区使用
   free     = 140384720 (133.8813018798828MB) ##伊甸区当前剩余容量
   34.65220164496263% used ##伊甸区使用情况
From Space: ##survior1区
   capacity = 26804224 (25.5625MB) ##survior1区容量
   used     = 3333984 (3.179534912109375MB) ##surviror1区已使用情况
   free     = 23470240 (22.382965087890625MB) ##surviror1区剩余容量
   12.43827838477995% used ##survior1区使用比例
To Space: ##survior2 区
   capacity = 26804224 (25.5625MB) ##survior2区容量
   used     = 0 (0.0MB) ##survior2区已使用情况
   free     = 26804224 (25.5625MB) ##survior2区剩余容量
   0.0% used ## survior2区使用比例
PS Old  Generation: ##老年代使用情况
   capacity = 1879048192 (1792.0MB) ##老年代容量
   used     = 30847928 (29.41887664794922MB) ##老年代已使用容量
   free     = 1848200264 (1762.5811233520508MB) ##老年代剩余容量
   1.6416783843721663% used ##老年代使用比例

Perm Generation: ##永久代使用情况
   capacity = 134217728 (128.0MB) ##perm区容量
   used     = 47303016 (45.111671447753906MB) ##perm区已使用容量
   free     = 86914712 (82.8883285522461MB) ##perm区剩余容量
   35.24349331855774% used ##perm区使用比例

显示堆中对象统计信息

jmap -histo:live 71217

这个指令可以和一些指令联和使用

jmap -histo pid|head -n 10 查看前10位(<font color=red>在cpu满载的时候这个指令极为重要,jmap全输出在cpu满载的时候是极为困难的J</font>)

jmap -histo pid | sort -k 2 -g -r 查看对象数最多的对象,按降序输出

jmap -histo pid | sort -k 3 -g -r 查看内存的对象,按降序输出

查看存活对象

root@server:~# jmap -histo:live 1999|head -n 10
 num     #instances(实例数)#bytes(字节大小)  class name
----------------------------------------------
   1:         36060        3520384  [C
   2:         36025         864600  java.lang.String
   3:          7193         790832  java.lang.Class
   4:          8458         744304  java.lang.reflect.Method
   5:         21820         698240  java.util.concurrent.ConcurrentHashMap$Node
   6:          2986         472512  [B
   7:          9424         376960  java.util.LinkedHashMap$Entry

补充说明

jmap 需要借助安全点机制,让所有线程停留在不改变堆中数据的状态,这可能导致基于该堆快照的分析结果存在偏差。

jstack 打印 JVM 中线程快照

jstack(JVM stack Trace):用于生成虚拟机指定进程当前时刻的线程快照(虚拟机堆栈跟踪)。

补充说明


  • 线程快照

    • 当前虚拟机内指定进程的每一条线程正在执行的方法堆栈的集合。
  • 生成线程快照的作用

    • 可用于定位线程出现长时间停顿的原因,如<font color=red>线程间死锁、死循环、请求外部资源导致的长时间等待</font>等问题。
  • 当线程出现停顿时,就可以用 jstack 显示各个线程调用的堆栈情况。

  • 在 thread dump 中,要留意下面几种状态:

    • 死锁,Deadlock (必须排查)
    • 等待资源,Waiting on condition (重点关注)
    • 等待获取监视器(锁),Waiting on monitor entry (重点关注)
    • 阻塞,Blocked (必须排查)
    • 执行中,Runnable
    • 暂停,Suspended
    • 对象等待中,Object.wait() 或 TIMED_WAITING
    • 停止,Parked

基本语法

jstack [option] pid

options

参数 含义
-F 当正常输出的请求不被响应时,强制输出线程堆栈
-I 除堆栈外,显示关于锁的附加信息
-m 如果调用到本地方法,可以显示 C/C++的堆栈
-h 帮助操作

案例

案例一:死锁

public static void main(String[] args) {
        StringBuilder s1 = new StringBuilder();
        StringBuilder s2 = new StringBuilder();
 
        Thread thread1 = new Thread("线程1") {
            @Override
            public void run() {
 
                synchronized (s1){
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (s2){
                        System.out.println("我是"+Thread.currentThread().getName());
                    }
                }
            }
        };
 
        Thread thread2 = new Thread("线程2") {
            @Override
            public void run() {
                synchronized (s2){
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (s1){
                        System.out.println("我是"+Thread.currentThread().getName());
                    }
                }
 
            }
        };
 
        thread1.start();
        thread2.start();
 
    }

jstack

root@server:~# jstack 2193
2021-06-18 06:07:31
Full thread dump OpenJDK 64-Bit Server VM (25.292-b10 mixed mode):


"线程2" #31 prio=5 os_prio=0 tid=0x00007f0468a06000 nid=0x8b8 waiting for monitor entry [0x00007f0409f09000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at com.study.prometheus.PromethuesDemoApplication$2.run(PromethuesDemoApplication.java:74)
        - waiting to lock <0x00000000ebb3abc0> (a java.lang.StringBuilder)
        - locked <0x00000000ebb3ac08> (a java.lang.StringBuilder)

"线程1" #30 prio=5 os_prio=0 tid=0x00007f0468c96800 nid=0x8b7 waiting for monitor entry [0x00007f040a00a000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at com.study.prometheus.PromethuesDemoApplication$1.run(PromethuesDemoApplication.java:58)
        - waiting to lock <0x00000000ebb3ac08> (a java.lang.StringBuilder)
        - locked <0x00000000ebb3abc0> (a java.lang.StringBuilder)


"VM Thread" os_prio=0 tid=0x00007f04681c8000 nid=0x89b runnable

"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00007f046801f800 nid=0x893 runnable

"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00007f0468021800 nid=0x894 runnable

"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x00007f0468023000 nid=0x895 runnable

"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x00007f0468025000 nid=0x896 runnable

"GC task thread#4 (ParallelGC)" os_prio=0 tid=0x00007f0468026800 nid=0x897 runnable

"GC task thread#5 (ParallelGC)" os_prio=0 tid=0x00007f0468028800 nid=0x898 runnable

"GC task thread#6 (ParallelGC)" os_prio=0 tid=0x00007f046802a000 nid=0x899 runnable

"GC task thread#7 (ParallelGC)" os_prio=0 tid=0x00007f046802c000 nid=0x89a runnable

"VM Periodic Task Thread" os_prio=0 tid=0x00007f0468215800 nid=0x8a4 waiting on condition

JNI global references: 1537

//快照里面会打印发现死锁
Found one Java-level deadlock:
=============================
"线程2":
  waiting to lock monitor 0x00007f03c4002198 (object 0x00000000ebb3abc0, a java.lang.StringBuilder),
  which is held by "线程1"
"线程1":
  waiting to lock monitor 0x00007f0430004048 (object 0x00000000ebb3ac08, a java.lang.StringBuilder),
  which is held by "线程2"

Java stack information for the threads listed above:
===================================================
"线程2":
        at com.study.prometheus.PromethuesDemoApplication$2.run(PromethuesDemoApplication.java:74)
        - waiting to lock <0x00000000ebb3abc0> (a java.lang.StringBuilder)
        - locked <0x00000000ebb3ac08> (a java.lang.StringBuilder)
"线程1":
        at com.study.prometheus.PromethuesDemoApplication$1.run(PromethuesDemoApplication.java:58)
        - waiting to lock <0x00000000ebb3ac08> (a java.lang.StringBuilder)
        - locked <0x00000000ebb3abc0> (a java.lang.StringBuilder)

Found 1 deadlock.


jstack -l

root@server:~# jstack -l 2193
2021-06-18 06:09:49
Full thread dump OpenJDK 64-Bit Server VM (25.292-b10 mixed mode):

"线程2" #31 prio=5 os_prio=0 tid=0x00007f0468a06000 nid=0x8b8 waiting for monitor entry [0x00007f0409f09000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at com.study.prometheus.PromethuesDemoApplication$2.run(PromethuesDemoApplication.java:74)
        - waiting to lock <0x00000000ebb3abc0> (a java.lang.StringBuilder)
        - locked <0x00000000ebb3ac08> (a java.lang.StringBuilder)
   //这里会打印锁信息
   Locked ownable synchronizers:
        - None

"线程1" #30 prio=5 os_prio=0 tid=0x00007f0468c96800 nid=0x8b7 waiting for monitor entry [0x00007f040a00a000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at com.study.prometheus.PromethuesDemoApplication$1.run(PromethuesDemoApplication.java:58)
        - waiting to lock <0x00000000ebb3ac08> (a java.lang.StringBuilder)
        - locked <0x00000000ebb3abc0> (a java.lang.StringBuilder)

   Locked ownable synchronizers:
        - None


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

   Locked ownable synchronizers:
        - None

"C1 CompilerThread3" #8 daemon prio=9 os_prio=0 tid=0x00007f0468210000 nid=0x8a2 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None

"C2 CompilerThread2" #7 daemon prio=9 os_prio=0 tid=0x00007f046820e000 nid=0x8a1 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None

"C2 CompilerThread1" #6 daemon prio=9 os_prio=0 tid=0x00007f046820c800 nid=0x8a0 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None

"C2 CompilerThread0" #5 daemon prio=9 os_prio=0 tid=0x00007f0468209800 nid=0x89f waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None

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

   Locked ownable synchronizers:
        - None

"Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007f04681d6800 nid=0x89d in Object.wait() [0x00007f0439f6c000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00000000c31bad68> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
        - locked <0x00000000c31bad68> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165)
        at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:216)

   Locked ownable synchronizers:
        - None

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

   Locked ownable synchronizers:
        - None

"VM Thread" os_prio=0 tid=0x00007f04681c8000 nid=0x89b runnable

"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00007f046801f800 nid=0x893 runnable

"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00007f0468021800 nid=0x894 runnable

"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x00007f0468023000 nid=0x895 runnable

"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x00007f0468025000 nid=0x896 runnable

"GC task thread#4 (ParallelGC)" os_prio=0 tid=0x00007f0468026800 nid=0x897 runnable

"GC task thread#5 (ParallelGC)" os_prio=0 tid=0x00007f0468028800 nid=0x898 runnable

"GC task thread#6 (ParallelGC)" os_prio=0 tid=0x00007f046802a000 nid=0x899 runnable

"GC task thread#7 (ParallelGC)" os_prio=0 tid=0x00007f046802c000 nid=0x89a runnable

"VM Periodic Task Thread" os_prio=0 tid=0x00007f0468215800 nid=0x8a4 waiting on condition

JNI global references: 1537


Found one Java-level deadlock:
=============================
"线程2":
  waiting to lock monitor 0x00007f03c4002198 (object 0x00000000ebb3abc0, a java.lang.StringBuilder),
  which is held by "线程1"
"线程1":
  waiting to lock monitor 0x00007f0430004048 (object 0x00000000ebb3ac08, a java.lang.StringBuilder),
  which is held by "线程2"

Java stack information for the threads listed above:
===================================================
"线程2":
        at com.study.prometheus.PromethuesDemoApplication$2.run(PromethuesDemoApplication.java:74)
        - waiting to lock <0x00000000ebb3abc0> (a java.lang.StringBuilder)
        - locked <0x00000000ebb3ac08> (a java.lang.StringBuilder)
"线程1":
        at com.study.prometheus.PromethuesDemoApplication$1.run(PromethuesDemoApplication.java:58)
        - waiting to lock <0x00000000ebb3ac08> (a java.lang.StringBuilder)
        - locked <0x00000000ebb3abc0> (a java.lang.StringBuilder)

Found 1 deadlock.

案例二:cpu满载

第一步:查看cpu占用高进程

top

Mem:  16333644k total,  9472968k used,  6860676k free,   165616k buffers
Swap:        0k total,        0k used,        0k free,  6665292k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND     
40433 root      20   0 7588m 112m  11m S 100.7  0.7  47:53.80 java       
 1552 root      20   0  121m  13m 8524 S  0.7  0.1  14:37.75 AliYunDun   
 3581 root      20   0 9750m 2.0g  13m S  0.7 12.9 298:30.20 java        
    1 root      20   0 19360 1612 1308 S  0.0  0.0   0:00.81 init        
    2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd    
    3 root      RT   0     0    0    0 S  0.0  0.0   0:00.14 migration/0 

第二步:查看高进程中cpu占用高线程

top -Hp 40433

top - 17:43:15 up 5 days,  7:31,  1 user,  load average: 0.99, 0.97, 0.91
Tasks:  32 total,   1 running,  31 sleeping,   0 stopped,   0 zombie
Cpu(s):  3.7%us,  8.9%sy,  0.0%ni, 87.4%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:  16333644k total,  9592504k used,  6741140k free,   165700k buffers
Swap:        0k total,        0k used,        0k free,  6781620k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
17880 root      20   0 7588m 112m  11m R 99.9  0.7  50:47.43 java
17856 root      20   0 7588m 112m  11m S  0.3  0.7   0:02.08 java
17850 root      20   0 7588m 112m  11m S  0.0  0.7   0:00.00 java
17851 root      20   0 7588m 112m  11m S  0.0  0.7   0:00.23 java
17852 root      20   0 7588m 112m  11m S  0.0  0.7   0:02.09 java
17853 root      20   0 7588m 112m  11m S  0.0  0.7   0:02.12 java
17854 root      20   0 7588m 112m  11m S  0.0  0.7   0:02.07 java

-H 显示线程信息,-p指定pid

第三步:转换线程ID

printf "%x\n" 40433          
9df3

第四步:定位cpu占用线程

root@server:~# jstack -l 2193
40433 DBService-1.2.7.jar
20584 Server
37417 QuorumPeerMain
13705 jar
30892 Jps
[hh_mpp_cd@sjsy-hh305-hx13w ~]$ jstack 40433|grep -10 9df3
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
        at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:834)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1415)
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
        - locked <0x000000079df35438> (a org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:748)

"http-nio-9372-exec-31" #5185 daemon prio=5 os_prio=0 tid=0x000000079df35438 nid=0x9df3 runnable [0x00007f86f9ad7000]
   java.lang.Thread.State: RUNNABLE                   //cpu占用高  该线程状态应为RUNNABLE
        at java.net.SocketOutputStream.socketWrite0(Native Method)
        at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:111)
        at java.net.SocketOutputStream.write(SocketOutputStream.java:155)
--
"Reference Handler" #2 daemon prio=10 os_prio=0 tid=0x00007f879c526000 nid=0x9e15 in Object.wait() [0x00007f8732dec000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        at java.lang.Object.wait(Object.java:502)
        at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
        - locked <0x00000006c00b4170> (a java.lang.ref.Reference$Lock)
        at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)

"VM Thread" os_prio=0 tid=0x00007f879c51c800 nid=0x9e14 runnable

"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00007f879c01f000 nid=0x9df3 runnable   //9df3 这个占用cpu高的线程为GC线程

"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00007f879c021000 nid=0x9df4 runnable

"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x00007f879c022800 nid=0x9df5 runnable

"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x00007f879c024800 nid=0x9df6 runnable

"GC task thread#4 (ParallelGC)" os_prio=0 tid=0x00007f879c026800 nid=0x9df7 runnable

"GC task thread#5 (ParallelGC)" os_prio=0 tid=0x00007f879c028000 nid=0x9df8 runnable

相关文章

网友评论

      本文标题:JVM监控-命令行

      本文链接:https://www.haomeiwen.com/subject/hutkyltx.html