JVM监控及诊断工具-命令行篇一
1 jps
基本概述
jps(java process status),用于查看正在运行的java虚拟机进程,会显示指定系统内所有的HotSpot虚拟机进程(查看虚拟机进程信息)。这里说明一下,对于本地虚拟机进程来说,进程的本地虚拟机ID与操作系统的进程ID是一致的且是唯一的。
初步测试
例如简单写一段程序:
public class ScannerTest {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);String info = scanner.next();} }然后这里使用Windows的命令行窗口,输入jps,就会显示我们刚启动的程序的信息:
以上的信息看起来比较简单,所展示的信息也不是很全面,为了更好的输出相关的信息,我们接下来看一下jps的语法。
基本语法
jps的基本语法如下:
jps [options] [hostid]当然我们还可以追加参数来输出一些额外的信息,另外我们也可以在命令行窗口输入jps -help看来查看对应的语法:
接下里说一下各个参数的含义,对于options,有不同的操作:
- -q:仅仅显示LVMID(local virtual machine id),即本地虚拟机唯一id,不显示主类的名称等;
- -l:输出应用程序主类的全类名或如果进程执行的jar包,则输出jar完整路径
- -m:输出虚拟机进程启动时传递给主类main()的参数
- -v:列出虚拟机进程启动时的JVM参数,比如-Xms20m,-Xmx50m。
我们接下来实际操作一下。使用jps -q,则只会显示对应的进程id:
使用jps -l,则显示对用进程的完成路径:
使用jps -m,发现信息比较多,我们将其输出到一个文件中进行查看,发现也没有什么特别的。
我们在IEDA中给入口函数增加输入参数likangmin,然后在重新看一下。
输出发现输出了对应的参数:
使用jps -v,显示jvm配置的虚拟机参数,我们打开IDEA的Configuration,配置一下信息:
表示设置jvm虚拟机堆内存大小最大和最小都是100m,然后我们使用jps -v,则可以查看到配置的信息:
当然我们还可以将这些信息组合使用,例如jps -lv,只不过可能信息量比较大,阅读起来不太方便,这里就不做演示,大家有兴趣可以自己输入命令行查看。需要注意一点-q是独立使用的。还有一点是如果某java进程关闭了默认开启的UsePerfData参数(即使用参数-XX:-UsePerfData),那么jps命令将无法探知该java进程。
再重新启动查看,发现已经找不到我们运行的进程了,此参数默认是开启的。
option说完,还有hostid, 支持的语法有< hostname>[: < port>],可以支持远程连接查看远程机器的参数信息,如果想要进行远程连接,需要安装jstatd。对于具有更严格的安全实践的网络场所而言,可能使用一个自定义的策略文件来显示对特定的可信主机或者网络的访问,尽管这种技术容易受到IP地址欺诈攻击。如果安全问题无法使用一个定制的策略文件来处理,那么最安全的操作还是不运行jstatd服务器,而是在本地使用jstat和jps工具。
2 jstat
基本概述
jstat(JVM statistic monitoring tool),用于监视虚拟机各种运行状态信息的命令行工具,它可以显示本地或者远程虚拟机进程中的类装载,内存,垃圾回收,JIT编译等运行数据。在没有GUI图形界面,只提供了纯文本控制台环境的服务器上,它将是运行期定位虚拟机性能问题的首选工具,常用于检测垃圾回收问题以及内存泄露问题。
基本语法
使用jstat -help查看一下jstat的基本语法
基本使用语法 jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]] 查看命令相关参数: jstat -h或jstat -help选项option可以由以下值构成:
- 类装载相关
- -class :显示ClassLoader的相关信息,包括类的装载和卸载数量,总空间,类装载所消耗的实践等
- 垃圾回收相关
- -gc :显示于GC相关的堆信息,包括Eden区,两个Survivor区,老年代,永久代等的容量,已用空间,GC时间合计等信息;
- -gccapacity :显示内容与 -gc 基本相同,但是输出主要关注Java堆各个区域使用到的最大,最小空间;
- -gcutil :显示内同与 -gc 基本相同,但输出主要关注已使用空间占总空间的百分比;
- -gccause :与 -gcutil功能一样,但是会额外输出导致最后一次或者当前正在发生的GC产生的原因;
- -gcnew :显示新生代GC的状况;
- -gcnewcapacity :显示内容与 -gcnew基本相同,输出主要关注使用到的最大,最小空间;
- -geold :显示老年代GC状况。
- JIT相关
- -compiler:显示JIT编译器编译过的方法,耗时等信息;
- -printcompilation :输出已经被JIT编译的方法。
我们首先以-class来进行说明,还是上面的例子,程序如下:
public class ScannerTest {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);String info = scanner.next();} }然后正常启动程序,在命令行中输入jps找到当前进程的id为38340
然后输入jstat -class 38340,出现以下信息:
这里是最简单的输出,我们没有带任何参数,以上信息含义如下:
接下来看一下interval和 count这两个参数:
interval:用于指定输出统计数据的周期,单位为毫秒,即查询间隔 count:用于指定查询的总次数如我们上面的例子中,没有指定interval和count参数,所以只会打印一次就结束,如果我们想每隔1000毫秒打印一次,则可以输入命令:jstat -class 38340 1000
以上是每隔一秒打印一次,有助于我们持续监控相关信息,但是因为没有指定组要输出的次数,所以会一直输出下去直到程序结束或者内存溢出,如果我们想打印10次就停止,那我们可以输入命令:jstat -class 38340 1000 10
输出打印十次以后就自动停止了。
接下里说一下-t参数,此参数在进程id的前面,在option的后面,可以在输出统计信息前加上一个Timestamp列,显示程序的运行时间,单位为秒。我们加入-t看一下输出的效果:jstat -class -t 38340
再执行一次时间增加:
最后还有一个参数-h,可以在周期性数据输出时,输出多少行数据后输出一个表头信息,在之前的周期性数据输出中,是在最开始的地方有把头的信息:
如果我们想输出3行就重新打印一次表头信息,则可以使用参数-h,后面直接跟上行数即可:jstat -class -t -h3 38340 1000 10
简答参数说完,我们再回到对于其他option的操作,首先说一下跟JIT相关的,还是同样的例子,我们你输入jstat -compiler 38340
大家看对应的属性就能知道是什么意思,表示编译过的方法的数目以及耗时。继续使用jstat -printcompilation 38340
表示已经被JIT编译的方法的数目以及大小等相关信息。
接下来是比较重要的垃圾回收相关的option操作,我们能将相关option再罗列一遍:
- -gc :显示于GC相关的堆信息,包括Eden区,两个Survivor区,老年代,永久代等的容量,已用空间,GC时间合计等信息;
- -gccapacity :显示内容与 -gc 基本相同,但是输出主要关注Java堆各个区域使用到的最大,最小空间;
- -gcutil :显示内同与 -gc 基本相同,但输出主要关注已使用空间占总空间的百分比;
- -gccause :与 -gcutil功能一样,但是会额外输出导致最后一次或者当前正在发生的GC产生的原因;
- -gcnew :显示新生代GC的状况;
- -gcnewcapacity :显示内容与 -gcnew基本相同,输出主要关注使用到的最大,最小空间;
- -geold :显示老年代GC状况。
接下里我们直接使用命令行进行操作,输入jstat -gc 38340
我们对以上参数做一下说明:
大家对照着看一下就可以知道以上输出表示的含义。以上是没有进行垃圾回收的情况,接下来我们换一个例子,代码如下:
代码比较简单,我们设置一下jvm相关参数-Xms60m -Xmx60m -XX:SurvivorRatio=8,启动程序,查看运行程序进程id为49580
然后输入jstat -gc 49580 1000 10,可以看到对应的垃圾回收的情况。
这里我们可以参数-t,来进行时间的计算。输入jstat -gc -t 13764 1000 10
从中选取两条输出的信息作为对比,两者的Timesatmp相减为程序运行的总时间,两者的GCT相减为运行期间垃圾回收的总时间,依据这些信息我们可以得出GC时间占运行时间的比例。如果该比例超过20%,则说明目前堆的压力比较大,如果该比例超过90%,则说明堆几乎没有可用空间,随时可能抛出OOM。
然后输入jstat -gcutil 51280 1000 10,可以看到展示信息与上面相似,只不过这里是以百分比的信息进行展示的。
输入jstat -gccause 45480 1000 10,显示垃圾回收失败的原因。
这里补充一点说明,jstat还可以用来判断是否出现内存泄漏,步骤如下:
3 jinfo
基本概述
jinfo(Configuration Info for Java),查看虚拟机配置参数信息,也可以用于调整虚拟机的配置参数。在很多情况下,Java应用程序不会指定所有的Java虚拟机参数。而此时,开发人员可能不知道某一个具体的Java虚拟机参数的默认值,在这种情况下,可能需要通过查找文档获取某个参数的默认值。这个查找过程是非常艰难的,但有了jinfo工具,开发人员可以很方便地找到Java虚拟机参数的当前值。
基本语法
同样使用-help看一下jinfo的基本语法:
我们将其用法与搭配的参数做一下总结然后再统一的进行实际操作,首先是针对查找的操作:
下面是针对修改的操作:
jinfo -flag [+|-]具体的参数 PID 针对boolean类型 jinfo -flag 具体的参数=具体的参数值 PID 针对非boolean类型当然还有其他的一些拓展指令:
java -XX:+PrintFlagsInitial 查看所有JVM参数启动的初始值 java -XX:+PrintFlagsFinal 查看所有JVM参数的最终值 java -XX:+PrintCommandLineFlags 查看那些已经被用户或者JVM设置过的详细的XX参数的名称和值接下来我们来进行实际操作看一下每一个指令具体的输出。还是使用之前的一个例子,代码如下:
public class ScannerTest {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);String info = scanner.next();} }同样使用JPS获取进程id为52200,首先我们对查找进行实践操作。
然后输入jinfo -sysprops 52200得到如下一些信息,这里我只截取了部分,基本都是可以通过System.getProperties()取得的参数,这里就不做过多说明。
输入jinfo -flags 52200,查看曾经赋值过的一些参数
在上面有两个地方需要注意,Non-default表示非默认的,Command line表示通过命令行赋值的。这里输出的是所有的参数的值,如果我们想看具体的某一个参数的值,则使用jinfo -flag 具体的参数 PID,例如要看是否使用了ParallelGC,则使用命令jinfo -flag UseParallelGC 52200
输出-XX:+UseParallelGC表示使用的是ParallelGC,再比如看一下最大堆空间的大小,则可以使用jinfo -flag MaxHeapSize 52200就可以得到对应的值。
其他参数也是类似的操作。以上就是查找的相关操作,接下来进行修改操作的实践。需要说明的是,jinfo并非所有的参数都支持动态修改,它的修改能力是极其有限的,参数只有被标记为manageable的flag可以被实时修改,修改以后立即生效。我们可以使用命令java -XX:+PrintFlagsFinal -version | grep manageable(linux指令)或java -XX:+PrintFlagsInitial | findstr manageable(window命令)查看被标记为manageable的参数:
例如我们修改 PrintGCDetails的值,首先看一下 PrintGCDetails的原先的值,使用指令jinfo -flag PrintGCDetails 52200,说明没有使用PrintGCDetails。
然后我们使用jinfo -flag +PrintGCDetails 52200进行修改
然后再次查看,已经发生了改变
上面的参数属于boolean类型,接下来我们修改一个非boolean类型的,例如MaxHeapFreeRatio,使用jinfo -flag MaxHeapFreeRatio 52200看一下原来的值为100
然后我们使用命令jinfo -flag MaxHeapFreeRatio=90 52200进行修改再进行查看发现已经修改成功。
有个问题需要说明的是如果当前进程结束,再重新开启,那么我们之前修改的数据也会失效。
最后一部分拓展的指令不做过多的说明,毕竟从解释上就已经很明确表示什么含义了。输入java -XX:+PrintFlagsFinal 查看所有JVM参数的最终值,下面只截取了部分数据,其中红色圈出来的表示修改之后的值(重新赋值过),其他的表示默认值没有进行过修改。其他的也类似,大家有兴趣可以使用指令输出看一下。
总结
以上是生活随笔为你收集整理的JVM监控及诊断工具-命令行篇一的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: 你知道Integer和int的区别吗
- 下一篇: 远程服务器安装docker和docker