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

Posted xyzshm

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入理解java虚拟机第二版虚拟机性能监控与故障处理工具相关的知识,希望对你有一定的参考价值。

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:DevelopJavajdk1.6.0_21in>jps-l
2388 D:Developglassfishin..modulesadmin-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:UsersIcyFenix>jmap-dump:format=b,file=eclipse.bin 3500
Dumping heap to C:UsersIcyFenixeclipse.bin……
Heap dump file created

 

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

使用jhat分析dump文件

C:UsersIcyFenix>jhat eclipse.bin
Reading from eclipse.bin……
Dump file created Fri Nov 19 220721 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虚拟机第二版虚拟机性能监控与故障处理工具的主要内容,如果未能解决你的问题,请参考以下文章

虚拟机性能监控与故障处理工具

精选资源深入理解Java虚拟机(第二版).pdf

深入理解Java虚拟机的目录

深入理解Java虚拟机之读书笔记四 性能监控与故障处理工具

深入理解Java虚拟机:JVM高级特性与最佳实践的内容简介

深入理解JAVA虚拟机 虚拟机性能监控和故障处理工具