首页 > 编程语言 > 详细

深入理解java虚拟机第二版(四)虚拟机性能监控与故障处理工具

时间:2020-03-31 09:27:52      阅读:95      评论:0      收藏:0      [点我收藏+]

JDK的命令行工具(jps:虚拟机进程状况工具,jstat:虚拟机统计信息监视工具,jinfo:Java配置信息工具,jmap:Java内存映像工具,jhat:虚拟机堆转储快照分析工具,jstack:Java堆栈跟踪工具);可视化工具(JConsole,VisualVM)

 

一. JDK的命令行工具

  • jps:JVM Process Status Tool,显示指定系统内所有的HotSpot虚拟机进程
  • jstat:JVM Statistics Monitoring Tool,用户收集HotSpot虚拟机各方面的运行数据
  • jinfo:Configuration Info for Java,显示虚拟机配置信息
  • jmap:Memory Map for java,生成虚拟机的内存转储快照
  • jhat,JVM Heap Dump Browser,用户分析heapdump文件,它会建立一个HTTP/HTML服务器,让用户可以在浏览器上查看分析结果
  • jstack, Stack Trace for Java,显示虚拟机的线程快照

1 jps:虚拟机进程状况工具

jsp命令格式:

jps [options] [hostid]

jps执行样例:
D:\Develop\Java\jdk1.6.0_21\bin>jps-l
2388 D:\Develop\glassfish\bin\..\modules\admin-cli.jar
2764 com.sun.enterprise.glassfish.bootstrap.ASMain
3788 sun.tools.jps.Jps
技术分享图片

 

2 jstat:虚拟机统计信息监视工具

jstat命令格式为:

jstat [option vmid[interval[s|ms][count]]]

参数interval和count代表查询间隔和次数,如果省略这两个参数,说明只查询一次。假设需要每250毫秒查询一次进程2764垃圾收集状况,一共查询20次,那命令应当是:

jstat -gc 2764 250 20

技术分享图片

 

jstat执行样例: jstat -gcutil 2764

S0   S1   E   O   P   YGC   YGCT   FGC   FGCT   GCT
0.00    0.00     6.20   41.42   47.20    16 0.  105     3    0.472     0.577

查询结果表明:这台服务器的新生代Eden区(E,表示Eden)使用了6.2%的空间,两个
Survivor区(S0、S1,表示Survivor0、Survivor1)里面都是空的,老年代(O,表示Old)和
永久代(P,表示Permanent)则分别使用了41.42%和47.20%的空间。程序运行以来共发生
Minor GC(YGC,表示Young GC)16次,总耗时0.105秒,发生Full GC(FGC,表示Full
GC)3次,Full GC总耗时(FGCT,表示Full GC Time)为0.472秒,所有GC总耗时(GCT,
表示GC Time)为0.577秒

 

3 jinfo:Java配置信息工具

jinfo命令格式:

jinfo [option] pid

执行样例:查询CMSInitiatingOccupancyFraction参数值。
C:\>jinfo-flag CMSInitiatingOccupancyFraction 1444
-XX:CMSInitiatingOccupancyFraction=85

 

4 jmap:Java内存映像工具

jmap命令格式:

jmap [option] vmid

技术分享图片

使用jmap生成dump文件
C:\Users\IcyFenix>jmap-dump:format=b,file=eclipse.bin 3500
Dumping heap to C:\Users\IcyFenix\eclipse.bin……
Heap dump file created

 

5 jhat:虚拟机堆转储快照分析工具

使用jhat分析dump文件

C:\Users\IcyFenix>jhat eclipse.bin
Reading from eclipse.bin……
Dump file created Fri Nov 19 22:07:21 CST 2010
Snapshot read,resolving……
Resolving 1225951 objects……
Chasing references,expect 245 dots……
Eliminating duplicate references……
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.

用户在浏览器中键入http://localhost:7000/就可以看到分析结果

技术分享图片

 

6 jstack:Java堆栈跟踪工具

jstack命令格式:

jstack[option]vmid

 

技术分享图片

 

二. JDK的可视化工具

JDK中除了提供大量的命令行工具外,还有两个功能强大的可视化工具:JConsole和VisualVM

1 JConsole:Java监视与管理控制台

1.1 启动JConsole

通过JDK/bin目录下的“jconsole.exe”启动

技术分享图片

 

技术分享图片

 

 

 1.2 内存监控

JConsole监视代码

/**
 * 内存占位符对象,一个OOMObject对象大约占64kb
 * -Xms 100m -Xmx 100m -XX:+UseSerialGC
 */
public class OOMObject {
    public byte[] placeholder = new byte[64*1024];
}
public class OOMObjectTest1 {
    public static void fillHeap(int num) throws InterruptedException {
        List<OOMObject> list = new ArrayList<OOMObject>();
        for (int i = 0; i < num; i++) {
            Thread.sleep(100);
            list.add(new OOMObject());
        }
        System.gc();
    }

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

技术分享图片

 

 

程序运行后,在“内存”页签中可以看到内存池Eden区的运行趋势呈现折线状,并且从柱状图可以看出,在1000次循环执行结束,运行了System.gc()后,虽然整个新生代Eden和Survivor区都基本被清空了,但是代表老年代的柱状图仍然保持峰值状态,说明被填充进堆中的数据在System.gc()方法执行之后仍然存活

 

1.3 线程监控 

线程等待演示代码

public class OOMObjectTest2 {
    /**
     *线程死循环演示
     */
    public static void createBusyThread(){
        Thread thread=new Thread(new Runnable(){
            public void run(){
                while(true)//第41行
                ;
            }
        },"testBusyThread");
        thread.start();
    }
    /**
     *线程锁等待演示
     */
    public static void createLockThread(final Object lock){
        Thread thread=new Thread(new Runnable(){
            public void run(){
                synchronized(lock){
                    try{
                        lock.wait();
                    }catch(InterruptedException e){
                        e.printStackTrace();
                    }
                }
            }
        },"testLockThread");
        thread.start();
    }
    public static void main(String[]args)throws Exception{
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        br.readLine();
        createBusyThread();
        br.readLine();
        Object obj=new Object();
        createLockThread(obj);
    }
}

程序运行后,首先在“线程”页签中选择main线程,堆栈追踪显示BufferedReader在readBytes方法中等待System.in的键盘输入, 这时线程为Runnable状态,Runnable状态的线程会被分配运行时间,但readBytes方法检查到流没有更新时会立刻归还执行令牌,这种等待只消耗很小的CPU资源。

技术分享图片

 

 

键盘输入值后,接着监控testBusyThread线程,线程一直在执行空循环,从堆栈追踪中看到一直在MonitoringTest.java代码的41行停留,41行为:while(true)。这时候线程为Runnable状态,而且没有归还线程执行令牌的动作,会在空循环上用尽全部执行时间直到线程切换,这种等待会消耗较多的CPU资源

技术分享图片

 

 

testLockThread线程在等待着lock对象的notify或notifyAll方法的出现,线程这时候处于WAITING状态,在被唤醒前不会被分配执行时间

技术分享图片

 

 

 

 死锁代码样例

public class SynAddRunalbe implements Runnable {
    int a,b;
    public SynAddRunalbe(int a,int b){
        this.a=a;
        this.b=b;
    }

    public void run(){
        synchronized(Integer.valueOf(a)){
            synchronized(Integer.valueOf(b)){
                System.out.println(a+b);
            }
        }
    }
}
public class OOMObjectTest3 {
    public static void main(String[]args){
        for(int i=0;i<100;i++){
            new Thread(new SynAddRunalbe(1,2)).start();
            new Thread(new SynAddRunalbe(2,1)).start();
        }
    }
}

出现线程死锁之后,点击JConsole线程面板的“检测到死锁”按钮,将出现一个新的“死锁”页签

技术分享图片

 

 

2 VisualVM:多合一故障处理工具

2.1 启动JConsole

通过JDK/bin目录下的“jvisualvm.exe”启动

技术分享图片

 

 

2.2 插件下载

 “工具”→“插件”→“已下载”菜单,然后在弹出的对话框中指定nbm包路径便可进行安装,插件安装后存放在JDK_HOME/lib/visualvm/visualvm中

插件中心地址:http://Visualvm java.net/pluginscenters.html。

 

 

声明:本文是个人学习笔记,内容来自《深入理解Java虚拟机·JVM高级特性与最佳实践》周志明 与网络文章

深入理解java虚拟机第二版(四)虚拟机性能监控与故障处理工具

原文:https://www.cnblogs.com/xyzshm/p/12602120.html

踩
(0)
赞
(0)
   
举报
评论 一句话评论(0)
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!