虚拟机性能监控命令行工具详解

JDK的这些工具都放在我们的JDK的安装目录的bin目录下,D:\ProgramFiles\Java\

jdk1.8.0_131\bin打开目录我们会发现除了常用的Java外,还有其他很多很多的工具,这些工具可以帮助我们来监控虚拟机的各种情况。 比较细心的同学,可能会注意到这些工具的程序体积都异常小巧。几乎所有工具的体积基本上都稳定在27KB左右。并非JDK开发团队刻意把它们制作得如此精炼来炫耀编程水平,而是因为这些命令行工具大多数是D:\

ProgramFiles\Java\jdk1.8.0_131\lib\jdk/lib/tools.jar类库的一层薄包装而已,它们主要的功能代码是在tools类库中实现的。

  1. 命令行工具
  1. jps

  有用过Linux系统的ps命令的同学给老师扣个1,Linux的查询进程命令ps一样。和Windows的任务管理器是一样的。jps的功能和ps命令相似:可列出正在运行的虚拟机进程,并显示虚拟机执行主类(Main Class,main()函数所在的类)名称以及这些进程的本地虚拟机唯一ID(Local Virtual Machine Identifier,LVMID)。我们来执行jps的命令:

首先要进入我们的JDK的bin目录下,执行命令:jps,会列出带有进程唯一ID(进程号)的一组数字,就是我们的PID,jps命令的其他命令参数为:

  1. jps -q  只列出进程ID,其他都不列
  2. jps -m  列出代码传给main方法的参数
  3. jps -l  输出当前运行主类的全称
  4. jps -v  输出虚拟机进程启动时JVM参数

jps虽然比较简单,但是如果你在Linux系统上对JAVA程序进行运维,Allen老师可以保证应该是使用频率最高的工具,因为下面的工具都需要用到这个pid。

(2)jstat

jstat(JVM Statistics Monitoring Tool)是用于监视虚拟机各种运行状态信息的命令行工 具。它可以显示本地或者远程[1]虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据,在没有GUI图形界面,只提供了纯文本控制台环境的服务器上,它将是运行期定位虚拟机性能问题的首选工具。

执行jstat的命令:我们可以看到可以跟[option],选项option代表着用户希望查询的虚拟机信息,主要分为3类:类装载、垃圾收集、运行期编译状况。可以跟VMID(唯一进程号),再跟interval和count代表查询间隔和次数,如果省略这两个参数,说明只查询一次。假设需要每250毫秒查询一次进程idea进程为40416垃圾收集状况,一共查询20次,那命令应当是: jstat -gc 40416 250 20执行结果中可以看出,S0C代表是Survivor0区,S1C代表是Survivor1区,C代表是容量的意思,U代表是已使用的意思,EC代表Eden区的容量,EU代表Eden区的使用。OC代表老年代的容量,OU代表老年代的使用。M代表元数据空间。CCSC和CCSU代表的是压缩类的容量大小和压缩类的使用空间大小,什么是压缩类的容量大小?这个概念我们后面会讲到。YGC的次数,YGCT回收年轻代所需的时间。FGC代表的是Full GC的次数,FGCT代表Full GC的时间,GCT代表垃圾回收

整个的时间。

我们要打印GC日志,jstat -gccause 40416  250 20 这个命令更关注的是GC原因

假如我们来监测新生代,jstat -gcnew 40416  250 20  这个命令就只会列出和新生代相关的部分。 假如我们来监测老年代, jstat -gcold 40416  250 20  这个命令就只会列出和老年代相关的部分。

(3)jinfo

jinfo(ConfigurationInfoforJava)的作用是实时地查看和调整虚拟机各项参数,使用jps命令的-v参数可以查看虚拟机启动时显式指定的参数列表,但如果想知道未被显式指定的参数的系统默认值,除了去找资料外,就只能使用jinfo的-flag选项进行查询了,我们来执行jinfo命令,会发现有很多的参数命令,看到了刚Allen老师说的-flag参数。例如我们来查询idea的进程是否开启了GC日志信息的详细打印,我们可以执行这样的命令:jinfo -flag PrintGCDetails 40416,从结果中我们可以看出是没有开启打印GC详细信息的。

  jinfo还可以使用-sysprops选项把虚拟机进程的System.getProperties()的内容打印出来,可以执行命令:jinfo -sysprops 40416。

 我们还可以实时的修改虚拟机的参数,但是不是任何命令都可以修改,可以修改的参数我们先来执行这个命令:java -XX:+PrintFlagsFinal -version,会列出当前机器支持的所有参数,那么用jinfo可以修改的参数是什么呢?只有最后一列显示manageable的这一列才能进行修改。

jinfo -flags:会打印当前该线程所有相关的参数,例如我们要来打印idea这个进程的所有相关参数,我们来执行命令:jinfo -flags 40416会列出JVM的版本,显示当前idea他的非缺省值的东西(也就是你修改过的),还有Command Line 代表的是命令行形式传递给idea这个进程的一些参数,刚我们说过jinfo可以去修改这些其中一部分的参数,能改manageable属性的这些参数。我们用一个代码来演示,来看JinfoTest类的代码,修改VM的参数:-Xmx20M -Xms20M -Xmn2m -XX:+PrintGC,执行代码我们看到了GC回收然后我们用jps -l来看下jinfo的进程ID,我们来打印下他的PrintGCDetails参数的值,jinfo -flag  PrintGCDetails 43280,可以看到我们没有开启这个参数,结果为-XX:-PrintGCDetails,我们来修改这个参数,改成:jinfo -flag +PrintGCDetails 43280,再来查看: jinfo -flag PrintGCDetails 43280,这个时候已经看到打印GC日志详情的开关已开启,程序也开始打印详细的GC日志。  

  那么jinfo适用在什么样的场景下?假如我们的生产环境要进行JVM调优,但是生产系统又不能重启,那么我们就可以登录生产平台用jinfo来修改加上打印GC详情的参数。这是jinfo给我们带来的最大的好处。

  1. jmap

jmap(Memory Map for Java)命令用于生成堆转储快照(一般称为heapdump或dump文件)。 jmap的作用并不仅仅是为了获取dump文件,它还可以查询finalize执行队列、Java堆和永久代的详细信息,如空间使用率、当前用的是哪种收集器等。和jinfo命令一样,jmap有不少功能在Windows平台下都是受限的,除了生成dump文件的-dump选项和用于查看每个类的实例、空间占用统计的-histo选项在所有操作系统都提供之外,其余选项都只能在Linux/Solaris下使用。我们执行jmap命令,我们可以看到有-dump的参数,我们先启动JinfoTest这个类,用jmap命令来生成我们的dump文件,我们先用jps -l先找出JinfoTest这个类的进程id,然后执行命令:jmap -dump:live,format=b,file=heap

.bin 31308 ,我们看到在bin目录下就产生了一个堆的转存文件。

  1.  jhat

既然生成了堆的转储快照文件,那么我们就要进行分析,我们怎么来分析,用我们的jhat来分析。怎么用?用jhat命令来打开:jhat heap.bin ,显示"Server is ready"时,就表示jhat已经把这个快照文件解开了。我们可以在浏览器中输入http://localhost:7000来查看分析结果。这个程序在堆中的相关信息,例如 All Class,代表JVM在启动这个类时要加载哪些类。以及一些其他的信息等等。

在实际工作中,一般都不会去直接使用jhat命令来分析dump文件,主要原因有二:一是一般不会在部署应用程序的服务器上直接分析dump文件,即使可以这样做,也会尽量将dump文件复制到其他机器上进行分析,因为分析工作是一个耗时而且消耗硬件资源的过程,既然都要在其他机器进行,就没有必要受到命令行工具的限制了;另一个原因是jhat的分析功能相对来说比较简陋,后文将会介绍到的VisualVM,以及专业用于分析dump文件的Eclipse MemoryAnalyzer、IBM HeapAnalyzer等工具,都能实现比jhat更强大更专业的分析功能。

  1. jstack

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

  如果要显示当前JinfoTest的java程序正在使用的所有线程和每个线程的调用栈都会打印出来。我们先来查询JinfoTest的进程,jps -l,然后我们执行jstack命令:jstack 31308,我们就看到了当前JinfoTest的java程序正在使用的所有线程和每个线程的调用栈都打印出来了。我们可以看到每个线程的状态,有处于等待的线程对吧?还有如果我们的线程中出现了死锁的时候,jstack会在最下面告诉我们当前哪两个线程出现了死锁,如果锁埋的比较深没有提示也没关系,我们在并发编程的课里面会教你如何去检查,其实就是看两个线程是不是持有对方的锁就行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值