JVM探秘(四)-Java虚拟机性能监控工具详解

一、jps命令详解

1.概述

jps(JVM Process Status Tool):可以列出正在运行的虚拟机进 程,并显示虚拟机执行主类(Main Class,main()函数所在的类)名称以及这些进程的本地虚拟机唯一 ID(LVMID,Local Virtual Machine Identifier)。LVMID即虚拟机实例运行时的进程号,比如我们同时运行三个Java程序,那么将会有与之对应的三个Java虚拟机实例,每一个虚拟机实例都有一个ID标识符。

2.使用方法

jps的命令格式如下:

jps [ options ] [ hostid ]
options:命令选项,用来对输出格式进行控制
hostid:指定特定主机,可以是ip地址和域名, 也可以指定具体协议,端口。格式为:[protocol:][[//]hostname][:port][/servername]

关于jps命令options选项参数为
在这里插入图片描述

3.应用举例

我们运行如下代码

import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class Test {
    public static void main(String[] args) {
        try{
            ServerSocket serverSocket = new ServerSocket();
            serverSocket.bind(new InetSocketAddress(8000));
            Socket accept = serverSocket.accept();
            System.out.println("收到客户端连接.....");
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

改代码启动一个ServerSocket等待一个客户端连接,由于accpet是阻塞方法,那么在未收到客户端连接时,不会退出阻塞,以便我们进行测试。现在我们打开命令行窗口,输入jps -l命令:
在这里插入图片描述
在这里插入图片描述
可以看到,jps显示我们运行程序的LVMID以及对应的包含报名的主类名称。
上述参数都比较简单,读者可自行尝试其他options参数。
使用jsp -m则不会显示包名。如图所示:
在这里插入图片描述

二、jstat命令详解

1.概述

jstat(JVM Statistics Monitoring Tool)是用于监视虚拟机各种运行状态信息的命令行工具。它可以显示本地或者远程 [1] 虚拟机进程中的类加载、内存、垃圾收集、即时编译等运行时数据。它是Java虚拟机性能监控的常用工具。

2.使用方法

jstat命令格式为:
jstat [ option vmid [interval[s|ms] [count]] ]
如果是本地虚拟机进程,VMID与LVMID是一致的;如果是远程虚拟机进程,那VMID的格式应当是:[protocol:][//]lvmid[@hostname[:port]/servername]

参数interval和count代表查询间隔和次数,如果省略这2个参数,说明只查询一次。在下文中我们会演示该参数。其中关于选项options的选项如图所示:
在这里插入图片描述

3. 应用举例

我们执行如下代码:

import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class Test01 {
    public static void main(String[] args) {
        try{
            ServerSocket serverSocket = new ServerSocket();
            serverSocket.bind(new InetSocketAddress(8000));
            Socket accept = serverSocket.accept();
            System.out.println("收到客户端连接.....");
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
class Person{
    
}
  1. jstat -class vmid
    打开命令行窗口,先使用jps命令查出该程序的LVMID。
    在这里插入图片描述
    经查询可知该程序的LVMID为2800。
    在命令行工具中输入jstat -class 2800,得到的结果如下所示:
    在这里插入图片描述
  • Loaded:装载的类的数量
  • Bytes:装载类所占用的字节数
  • Unloaded:卸载类的数量
  • Bytes:卸载类的字节数
  • Time:装载和卸载类所花费的时间

在上述代码中,添加一行代码,如图所示:
在这里插入图片描述
在重新运行,重复上述步骤:
在这里插入图片描述
可以看到Loaded的数量增加了1。是因为虚拟机在执行new指令时,会去加载Person类。
2. jstat -gc vmid
仍然运行上述代码,执行jstat -gc vmid 命令,得到的结果如下所示:
在这里插入图片描述

  • S0C:年轻代中第一个survivor(幸存区)的容量 (字节)
  • S1C :年轻代中第二个survivor(幸存区)的容量 (字节)
  • S0U:年轻代中第一个survivor(幸存区)目前已使用空间 (字节)
  • S1U:年轻代中第二个survivor(幸存区)目前已使用空间 (字节)
  • EC:年轻代中Eden(伊甸园)的容量 (字节)
  • EU:年轻代中Eden(伊甸园)目前已使用空间 (字节)
  • OC 老年代的容量 (字节)
  • OU:老年代代目前已使用空间 (字节)
  • PC:Perm(持久代)的容量 (字节)
  • PU:Perm(持久代)目前已使用空间 (字节)
  • YGC:从应用程序启动到采样时年轻代中gc次数
  • YGCT:从应用程序启动到采样时年轻代中gc所用时间(s)
  • FGC:从应用程序启动到采样时老年代代(全gc)gc次数
  • FGCT:从应用程序启动到采样时老年代(全gc)gc所用时间(s)
  • GCT:从应用程序启动到采样时gc用的总时间(s)

从上述图片可以看出,EC的总容量为130048K,已经使用了5201.9K。我们添加如下代码:
在这里插入图片描述

我们在通过jps命令先查出LVMID,在使用jstat命令,得到如下结果:
在这里插入图片描述
可以看到,60*1024+5201正好与66642相近。我们创建了一个60M的数组,它分配在了新生代。我们还可以持续监视变化,执行如下命令:
在这里插入图片描述
该命令的含义为:每个250毫秒检测一次,一共循环20次。
我们再次修改代码为:
在这里插入图片描述
在使用jstat查询:
在这里插入图片描述
我们可以看到,这个对象直接分配到了老年代,这是因为虚拟机的内存分配策略包含大对象直接进入老年代。具体细节我们在后续的博文中再详述。

三、jmap命令

1、概述

jmap(Memory Map for Java)命令用于生成堆转储快照。堆转储是反应Java堆使用情况的内存镜像,其中主要包括系统信息、虚拟机属性、完整的线程Dump、所有类和对象的状态等。 一般,在内存不足、GC异常等情况下,这个时候我们就可以制作堆Dump来查看具体情况,分析原因。

2、使用方法

jmap的命令格式为:

jmap [ option ] vmid

其中option选项如图所示:
在这里插入图片描述

3、应用举例

我们运行如下程序:

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

public class Test {
    public static void main(String[] args) {
        List<byte[]> list = new ArrayList<byte[]>();
        while(true){
            if(list.size() <20){
                list.add(new byte[1024*1024*5]);
                try{
                    Thread.sleep(2000);
                }catch (Exception e){

                }
            }else{
                break;
            }
        }
        try{
            Thread.sleep(300000);
        }catch (Exception e){

        }
    }
}

该程序是每隔两秒向arrayList中添加一个5M的字节数组。一共添加20个,当添加完毕后,休眠五分钟,之后程序退出。
执行程序后,我们使用jps找到该程序的LVMID。如图所示:
在这里插入图片描述
之后,使用jstat命令每隔两秒检测内存变化:
jstat -gc 16620 2000
在这里插入图片描述
从图中我们可以看到EU的所占的容量在不断的增长。待增长平稳后,我们新开一个命令行窗口运行jamp命令。
jmap -dump:format=b,file=Test.bin 16620
之后,该命令会生成Test.bin文件,这个文件可以用jvisualvm.exe程序打开,该程序在jps、jstat等工具的同级目录下:jdk1.8.0_91\bin。
打开该工具后,点击左上角的文件->装入,选择刚刚生成的文件。
在这里插入图片描述
在这里插入图片描述
我们从图中可以发现,byte[]类型的数组占据了在生成dump文件时刻,堆空间的97.8%。这时我们就应该去检查自己的程序,在哪个地方不断的产生对象填充到堆空间。其余命令读者可自行尝试。
本文未完待续。

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值