JVM调优监控常用工具

命令行工具

jps

(JVM Process Status Tool),类似于Linux的ps命令,用于列举正在运行的虚拟机进程,并显示虚拟机执行主类(main函数所在的类)名称以及这些进程的本地虚拟机唯一ID(LVMID local virtual machine Identifier)。

 jps [-q] [-mlvV] [<hostid>]

-q:只输出LVMID,省略主类的名称。

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

-l:输出主类的全名,如果进程执行的是jar包,输出jar路径。

-v:输出虚拟进程启动时JVM参数。

jps -q
8424
5180
8268

jstat

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

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

vmid :如果是本地虚拟机进程,VMID和LVMID是一致的。

interval:表示查询间隔。

count:表示查询次数。

如果省略interval,count两个参数,表示只查询一次。

option具体现象和作用如下:

-class:监视类装载、卸载数量、总空间以及类装载所耗费的时间。
-compiler:输出JIT编译器编译过的方法、耗时等信息。
-gc:监视java堆状况,包括Eden区,survivor区,老年代,永久代等的容量,已用空间、GC时间合计等信息。
-gccapacity:监视内容和-gc基本相同,但输出主要关注Java堆各个区域使用到的最大、最小空间。
-gccause:与gcutil功能一样,但是会额外输出导致上一次GC产生的原因。
-gcmetacapacity:显示有关元空间大小的统计信息。
-gcnew:监视新生代GC状况。
-gcnewcapacity:监视内容与-gcnew基本相同,输出主要关注使用到的最大、最小空间。
-gcold:监视老年代的GC状况。
-gcoldcapacity:监视内容与-gcold基本相同,输出主要关注使用到的最大、最小空间。
-gcutil:监视内容和-gc基本相同,但输出主要已使用空间占总空间的百分比。
-printcompilation:输出已经被JIT编译的方法。

jstat -gc 5180 1000 10
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
5120.0 5120.0 3825.2  0.0   33280.0  25547.9   87552.0      8.0     17536.0 17143.3 2176.0 2005.4      2    0.017   0      0.000    0.017
5120.0 5120.0 3825.2  0.0   33280.0  25547.9   87552.0      8.0     17536.0 17143.3 2176.0 2005.4      2    0.017   0      0.000    0.017
5120.0 5120.0 3825.2  0.0   33280.0  25547.9   87552.0      8.0     17536.0 17143.3 2176.0 2005.4      2    0.017   0      0.000    0.017
5120.0 5120.0 3825.2  0.0   33280.0  25547.9   87552.0      8.0     17536.0 17143.3 2176.0 2005.4      2    0.017   0      0.000    0.017
5120.0 5120.0 3825.2  0.0   33280.0  25547.9   87552.0      8.0     17536.0 17143.3 2176.0 2005.4      2    0.017   0      0.000    0.017
5120.0 5120.0 3825.2  0.0   33280.0  25547.9   87552.0      8.0     17536.0 17143.3 2176.0 2005.4      2    0.017   0      0.000    0.017
5120.0 5120.0 3825.2  0.0   33280.0  25547.9   87552.0      8.0     17536.0 17143.3 2176.0 2005.4      2    0.017   0      0.000    0.017
5120.0 5120.0 3825.2  0.0   33280.0  25547.9   87552.0      8.0     17536.0 17143.3 2176.0 2005.4      2    0.017   0      0.000    0.017
5120.0 5120.0 3825.2  0.0   33280.0  25547.9   87552.0      8.0     17536.0 17143.3 2176.0 2005.4      2    0.017   0      0.000    0.017
5120.0 5120.0 3825.2  0.0   33280.0  25547.9   87552.0      8.0     17536.0 17143.3 2176.0 2005.4      2    0.017   0      0.000    0.017

S0C:当前survivor space 0总容量(kB)
S1C:当前survivor space 1总容量(kB)
S0U:survivor space 0已使用容量(kB)
S1U:survivor space 1已使用容量(kB)
EC:当前eden space总容量(kB)
EU:eden space已使用容量(kB)
OC:当前old space总容量(kB)
OU:old space的已使用容量(kB)
MC:Metaspace 总容量(kB)
MU:Metacspace已使用容量(kB)
CCSC:压缩类空间总容量(kB)
CCSU:已使用的压缩类空间容量(kB)
YGC:Young generation GC次数
YGCT:Young generation GC总耗时
FGC:Full GC次数
FGCT:Full GC总耗时
GCT:GC总耗时

jinfo

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

格式

     jinfo [ option ] pid

     jinfo [ option ] executable core

     jinfo [ option ] [server-id@]remote-hostname-or-IP

参数说明

     pid  对应jvm的进程id

     executable core 产生core dump文件

     [server-id@]remote-hostname-or-IP  远程的ip或者hostname,server-id标记服务的唯一性id

option

     no option   输出全部的参数和系统属性

     -flag  name  输出对应名称的参数

     -flag [+|-]name  开启或者关闭对应名称的参数

     -flag name=value  设定对应名称的参数

     -flags  输出全部的参数

     -sysprops  输出系统属性

jinfo 5180
Attaching to process ID 5180, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.181-b13
Java System Properties:

java.vendor = Oracle Corporation
preload.project.path = E:/Java/jvm
sun.java.launcher = SUN_STANDARD

...

jinfo -flags 5180
Attaching to process ID 5180, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.181-b13
Non-default VM flags: -XX:CICompilerCount=3 -XX:InitialHeapSize=134217728 -XX:MaxHeapSize=734003200 -XX:MaxNewSize=244318208 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=44564480 -XX:OldSize=89653248 -XX:
+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC
Command line:  -Xmx700m -Djava.awt.headless=true -Djava.endorsed.dirs="" -Djdt.compiler.useSingleThread=true -Dpreload.project.path=E:/Java/jvm -Dpreload.config.path=C:/Users/chuang.ji/.IntelliJIdea20
18.3/config/options -Dcompile.parallel=false -Drebuild.on.dependency.change=true -Djava.net.preferIPv4Stack=true -Dio.netty.initialSeedUniquifier=-2925694128290007609 -Dfile.encoding=GBK -Duser.langua
...

jmap

(Memory Map for Java) 命令用于生成堆转储快照(一般称为heapdump或dump文件)。另外它还可以查下finalize执行队列、Java堆和永久代的详细情况。不过jmap有一些功能在Windows平台受限。

命令格式:

 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)

option可以是如下选项:

  <none>               to print same info as Solaris pmap
  -heap                to print java heap summary
  -histo[:live]        to print histogram of java object heap; if the "live"
                       suboption is specified, only count live objects
  -clstats             to print class loader statistics
  -finalizerinfo       to print information on objects awaiting finalization
  -dump:<dump-options> to dump java heap in hprof binary format
                       dump-options:
                         live         dump only live objects; if not specified,
                                      all objects in the heap are dumped.
                         format=b     binary format
                         file=<file>  dump heap to <file>
                       Example: jmap -dump:live,format=b,file=heap.bin <pid>
  -F                   force. Use with -dump:<dump-options> <pid> or -histo
                       to force a heap dump or histogram when <pid> does not
                       respond. The "live" suboption is not supported
                       in this mode.
  -h | -help           to print this help message
  -J<flag>             to pass <flag> directly to the runtime system

jstack

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

命令格式:
    jstack [-l] <pid>
        (to connect to running process)
    jstack -F [-m] [-l] <pid>
        (to connect to a hung process)
    jstack [-m] [-l] <executable> <core>
        (to connect to a core file)
    jstack [-m] [-l] [server_id@]<remote server IP or hostname>
        (to connect to a remote debug server)

option选项:

    -F 当正常输出的请求不被响应时,强制输出线程堆栈。

    -l 除堆栈外,显示锁的附加信息。

    -m 打印java和native c/c++框架的所有栈信息

可视化工具

jconsole

(ava Monitoring and Management Console是一种基于JMX的可视化监视、管理工具。

启动JConsole

通过JDK/bin目录下的jconsole.exe启动JConsole后,将会自动搜索本机运行的所有虚拟机进程,双击选择其中一个进程即可开机监控,也可以使用下面的“远程进程”功能来连接远程服务器,对远程虚拟机进行监控。

进入JConsole主界面后可以看到主界面包括“概览”,“内存”,“线程”,“类”,“VM概要”,“MBean”。

“概览”页签显示的是整个虚拟机注意运行数据的概览,其中包括“堆内存使用情况”、“线程”、“类”、“CPU事情情况”4种信息的曲线图。这些曲线图是后面“内存”、“线程”,“类”页签的信息汇总。

内存监控

“内存”页签相对于可视化的jstat命令,用于监视受收集器管理的虚拟机内存(Java堆和永久代)的变化趋势。

运行下面的程序,同时利用JConsole进行监控:

import java.util.ArrayList;
import java.util.List;

public class jconsoledemo1 {
    static class OOMObject{
        public byte[] placeholder = new byte[64*1024];
    }

    public static void fillHeap(int num) throws InterruptedException{
        Thread.sleep(10000);
        List<OOMObject> list = new ArrayList<OOMObject>();
        for(int i = 0; i < num; i++){
            Thread.sleep(50);
            list.add(new OOMObject());
        }
        System.gc();
    }

    public static void main(String[] args) throws Exception{
        fillHeap(1000);
    }
}

JVM的配置:-Xms100m -Xmx100m -XX:+UseSerialGC -XX:+PrintGCDetails

GC日志

[GC (Allocation Failure) [DefNew: 27328K->3392K(30720K), 0.0264937 secs] 27328K->11669K(99008K), 0.0268020 secs] [Times: user=0.02 sys=0.00, real=0.03 secs] 
[GC (Allocation Failure) [DefNew: 30693K->3373K(30720K), 0.0381057 secs] 38970K->36132K(99008K), 0.0381500 secs] [Times: user=0.00 sys=0.03, real=0.04 secs] 
[GC (Allocation Failure) [DefNew: 30645K->3365K(30720K), 0.0270089 secs] 63404K->61645K(99008K), 0.0270596 secs] [Times: user=0.03 sys=0.00, real=0.03 secs] 
[Full GC (System.gc()) [Tenured: 58279K->66334K(68288K), 0.0267295 secs] 67333K->66334K(99008K), [Metaspace: 9583K->9583K(1058816K)], 0.0267930 secs] [Times: user=0.02 sys=0.00, real=0.03 secs] 
Heap
 def new generation   total 30720K, used 476K [0x00000000f9c00000, 0x00000000fbd50000, 0x00000000fbd50000)
  eden space 27328K,   1% used [0x00000000f9c00000, 0x00000000f9c77328, 0x00000000fb6b0000)
  from space 3392K,   0% used [0x00000000fba00000, 0x00000000fba00000, 0x00000000fbd50000)
  to   space 3392K,   0% used [0x00000000fb6b0000, 0x00000000fb6b0000, 0x00000000fba00000)
 tenured generation   total 68288K, used 66334K [0x00000000fbd50000, 0x0000000100000000, 0x0000000100000000)
   the space 68288K,  97% used [0x00000000fbd50000, 0x00000000ffe17958, 0x00000000ffe17a00, 0x0000000100000000)
 Metaspace       used 9589K, capacity 9954K, committed 10240K, reserved 1058816K
  class space    used 1131K, capacity 1242K, committed 1280K, reserved 1048576K

线程监控

“线程”页签的功能相对于可视化的jstack命令,遇到线程停顿时可以使用这个页签进行监控分析。线程长时间停顿的主要原因有:等待外部资源(数据库连接,网络资源,设备资源等),死循环,锁等待(活锁和死锁)

/**
 * 线程死锁等待演示
 */
public class jconsoledemo3 {
    static class SynAddRunable implements  Runnable{
        int a, b;
        public SynAddRunable(int a,int b){
            this.a = a;
            this.b = b;

        }
        @Override
        public  void  run(){
            synchronized (Integer.valueOf(a)){
                synchronized (Integer.valueOf(b)){
                    System.out.println(a+b);
                }
            }
        }
    }

    public static void main(String [] args){
        for (int i =0; i< 100; i++){
            new Thread(new SynAddRunable(1,2)).start();
            new Thread(new SynAddRunable(2,1)).start();
        }
    }
}

这段代码开了200个线程去计算1+2和2+1的值,可能会导致死锁。造成死锁的原因是Integer.valueOf()方法基于减少对象创建次数和节省内存的考虑,[-128,127]之间的数字会被缓存,当valueOf()方法传入参数在这个范围之内,将之间返回缓存中的对象。也就是说,代码中调用了200次Integer.valueOf()方法,一共返回了两个不同的对象。假如在某个线程的两个synchronized块之间发生了一次线程切换,那就会出现线程A等着被线程B持有的Integer.valueOf(1),线程B又等着被线程A持有的Integer.valueOf(2),结果出现大家都跑不下去的情况。

 

线程-121等待一共被线程-192持有的Integer对象,而线程-192也等待一个被线程-121持有的Integer对象。这样两个线程就互相卡住,都不存在等待锁释放的希望。

VisualVM

VisualVM(All-in-One Jave Troubleshooting Tool)是随JDK发布的功能强大的运行监视和故障处理程序。它除了运行监视、故障处理外,还提供了许多其他方面的功能,如性能分析。和JProfiler,YourKit等专业Profiling工具相比,VisualVM还有一个很大的优点:不需要被监视的程序基于特殊agent运行,因此它对应用程序的实际性能影响很小,使得它可以直接应用在生产环境中。

VisualVm可以做到如下:

显示虚拟机进程以及进程的配置、环境信息。

监视应用程序的 CPU、GC、堆、方法区以及线程的信息。

dump以及分析堆转储快照。

方法级的程序运行性能分析,找出被调用最多,运行时间最长的方法。

离线程序快照:收集程序的运行时配置、线程dump、内存dump等信息建立一个快照,可以将快照发送给开发者进行Bug反馈。

启动VisualVM ,在目标应用程序中右击,选择"堆dump"或"线程dump",生成dump文件后,可以保存此文件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值