前面有一定的了解jvm、这里就了解一下怎么查看虚拟机,也就是对jvm的一个监控。
这里主要讲解jvm的相关工具以及使用:
1定义问题的思路
给一个系统定位问题的时候,知识,经验是关键基础,数据是依据,工具是运用知识处理数据的手段。这里说的数据包括:运行日志,异常堆栈,GC日志,线程快照,堆转储快照等;
2 jvm工具之jdk的命令行工具
jdk 的bin 目录是jdk的工具目录,这些命令行工具大多数是 jdk/lib/tools.jar 类库的一层薄包装而已,它们主要的功能代码是在 tools 类库中实现的;
介绍一下Sun JDK 监控和故障处理工具如下列表
一下就介绍一下jdk自带的这6个命令行工具:
2.1 jps 虚拟机进程状况工具(jps==jvm process status tool)
它可以列出正在运行的虚拟机进程,并显示虚拟机执行主类名称以及这些进程的本地虚拟机唯一ID;
jps用来查看基于HotSpot的JVM里面中,所有具有访问权限的Java进程的具体状态, 包括进程ID,进程启动的路径及启动参数等等,与unix上的ps类似,只不过jps是用来显示java进程,可以把jps理解为ps的一个子集。 使用jps时,如果没有指定hostid,它只会显示本地环境中所有的Java进程;如果指定了hostid,它就会显示指定hostid上面的java进程,不过这需要远程服务上开启了jstatd服务,可以参看前面的jstatd章节来启动jstad服务。
命令格式 :jps [ options ] [ hostid ]
参数说明 :
-q 忽略输出的类名、Jar名以及传递给main方法的参数,只输出pid。
-m 输出传递给main方法的参数,如果是内嵌的JVM则输出为null。
-l 输出应用程序主类的完整包名,或者是应用程序JAR文件的完整路径。
-v 输出传给JVM的参数。
-V 输出通过标记的文件传递给JVM的参数(.hotspotrc文件,或者是通过参数-XX:Flags=<filename>指定的文件)。
-J 用于传递jvm选项到由javac调用的java加载器中,例如,“-J-Xms48m”将把启动内存设置为48M,使用-J选项可以非常方便的向基于Java的开发的底层虚拟机应用程序传递参数。下面样例均在linux的jdk1.7下测试。
使用样例:
-
[root
@tools138 ~]# jps
-
-
2897 Bootstrap
-
-
22558 Jps
-
-
[root
@tools138 ~]# jps -l
-
-
2897 org.apache.catalina.startup.Bootstrap
-
-
22568 sun.tools.jps.Jps
-
-
[root
@tools138 ~]# jps -v
-
-
2897 Bootstrap -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.endorsed.dirs=/usr/local/tomcat/endorsed -Dcatalina.base=/usr/local/tomcat -Dcatalina.home=/usr/local/tomcat -Djava.io.tmpdir=/usr/local/tomcat/temp
-
-
22578 Jps -Denv.class.path=/usr/java/jdk1.7.0/lib -Dapplication.home=/usr/java/jdk1.7.0 -Xms8m
2.2 jstat:虚拟机统计信息监视工具(jstat==jvm statistics monitoring tool)
用于监视虚拟机各种运行状态信息的命令行工具。他可以显示本地或者远程虚拟机进程中的类装载,内存,垃圾收集,JIT编译等运行数据,在没有GUI的时候,它是运行期定位虚拟机性能问题的首选工具;
Jstat用于监控基于HotSpot的JVM,对其堆的使用情况进行实时的命令行的统计,使用jstat我们可以对指定的JVM做如下监控:
- 类的加载及卸载情况
- 查看新生代、老生代及持久代的容量及使用情况
- 查看新生代、老生代及持久代的垃圾收集情况,包括垃圾回收的次数及垃圾回收所占用的时间
- 查看新生代中Eden区及Survior区中容量及分配情况等
jstat工具特别强大,它有众多的可选项,通过提供多种不同的监控维度,使我们可以从不同的维度来了解到当前JVM堆的使用情况。详细查看堆内各个部分的使用量,使用的时候必须加上待统计的Java进程号,可选的不同维度参数以及可选的统计频率参数。
命令格式:
jstat [ option vmid [interval] [s|ms] [count]]
对于命令格式中的 VMID和 LVMID。
如过是本地虚拟机进程,VMID和LVMID是一致的,
如果是远程虚拟机,那VMID的格式应当是:[protocol:] [//] lvmid[@hostname[:port]rvername].
参数interval 和count分别表示查询的间隔和次数,如果省略这两个参数,说明只查询一次。
如需要每250ms 查询一次进程 2764 垃圾收集状况,一共查询20次,命名应该是: jstat -gc 2764 250 20
选项option代表着用户希望查询的虚拟机信息,主要分为三类:类装载,垃圾收集、运行期编译状况、列表如下。
本地jstal使用案例:
注意:使用-gc会更加详细,只是因为整齐使用了gcutil。
介绍查询结果:
S0、S1 代表两个Survivor区(Survivor0和Survivor1);
E 代表 新生代的Eden 区;
O(Old)代表老年代;
P(Permanent)代表永久代;
YGC(Young GC)代表Minor GC;
YGCT代表Minor GC耗时;
FGC(Full GC)代表Full GC耗时;
GCT代表Minor & Full GC共计耗时。
Java 堆分为新生代和老年代,新生代一般划分为三块区域,Eden + From Survivor + To Survivor,Eden 和 Survivor 的内存比为8:1,每次只使用一个Eden 和一个 Survivor 区域,另一个 Survivor 用于复制收集算法回收内存。
下面的 86.19 是指使用了该区的多少空间百分之多少的空间。
使用gc的情况:
详细介绍:
其他以gc开始的结果列跟gc选项结果列基本一样,这里不一一列举了。
2.3 jinfo:java配置信息工具
jinfo可以输出并修改运行时的java 进程的opts。用处比较简单,用于输出JAVA系统参数及命令行参数。
jinfo的作用(function):
1>实时地查看和调整虚拟机各项参数。使用jps命令的-v 参数可以查看jvm启动时显式指定的参数列表,但如果想知道未被显式指定的参数的系统默认值,就只能使用 jinfo的-flag 选项进行查询了;
2>jinfo还可以使用 -sysprops 选项把jvm 进程的 System.getProperties()的内容打印出来;
3>jinfo加入了运行期修改参数的能力,可以使用 -flag[+|-] name 或 -flag name=value 修改一部分运行期可写的jvm 参数值;(jinfo 在 windows平台的功能有较大限制,只提供了最基本的-flag选项)
命令格式:
jinfo [option] pid
使用样例:jinfo [option] pid //pid 通过 jps 来查看
在linux下使用:
-
[root
@tools138 ~]# jinfo -flag MaxNewSize
2897
-
-
-XX:MaxNewSize=
18446744073709486080
例如在win下的查看:
-
F:\Java\jdk\jdk1.7.0_60\bin>jinfo
25592
-
Attaching to process ID
25592, please wait...
-
Debugger attached successfully.
-
Server compiler detected.
-
JVM version is
24.60-b09
-
Java System Properties:
-
-
java.vendor = Oracle Corporation
-
sun.java.launcher = SUN_STANDARD
-
catalina.base = C:\Users\mch\.IntelliJIdea2017.1\system\tomcat\Unnamed_hy_logistics
-
sun.management.compiler = HotSpot
64-Bit Tiered Compilers
-
catalina.useNaming =
true
-
os.name = Windows
8.1
-
sun.boot.class.path = F:\Java\jdk\jdk1.7.0_60\jre\lib\resources.jar;
-
com.sun.management.jmxremote =java.vm.specification.vendor = Oracle Corporation
-
java.runtime.version =
1.7.0_60-b19
-
user.name = mch
-
...省略一大部分
-
java.vm.name =
Java HotSpot(TM) 64-Bit Server VM
-
file.encoding = GBK
-
java.specification.version =
1.7
-
-
VM Flags: ...省略一大部分
2.4 jmap:java内存映像工具(memory map for java):
jmap用于生成堆转储快照(一般称为heapdump或者dump文件)。当然也可其他方法比如加参数-XX:+HeapDumpOnOutOfMemoryError参数,在虚拟机OOM异常的之后自动生成dump文件,也可以通过-XX:+HeapDumpOnCtrlBreak参数则可以使用Ctrl+Break键让虚拟机生成dump文件。在前文测试中就有生成。dump文件生成后可借助jha、MAT( Eclipse Memory Analyzer tool)、IBM HeapAnalyzer来对dump分析。jmap不仅能获取dump还可以查询finalize执行队列,java堆和永久代详细信息,空间使用率,当前用的是什么收集器等。
jmap的作用并不仅仅是为了获取dump文件,它还可以查询 finalize 执行队列,java堆和永久代的详细信息;
命令格式:jmap [ option ] pid
option的合法值和具体含义如下表:
使用案例:
-
F:\Java\jdk\jdk1.7.0_60\bin>jps -l
-
15692 sun.tools.jps.Jps
-
25592 org.apache.catalina.startup.Bootstrap
-
6276 org.jetbrains.jps.cmdline.Launcher
-
3976
-
-
F:\Java\jdk\jdk1.7.0_60\bin>jmap -dump:format=b,file=eclipse.bin
25592
-
Dumping heap to F:\Java\jdk\jdk1.7.0_60\bin\eclipse.bin ...
-
Heap dump file created
-
-
F:\Java\jdk\jdk1.7.0_60\bin>
2.5 jhat:虚拟机堆转储快照分析工具
jhat是sun提供的dump分析工具,上面讲过分析dump的工具还有MAT( Eclipse Memory Analyzer tool)、IBM HeapAnalyzer等,一般这个命令不太用到,是因为分析dump是个既耗时又耗机器资源的过程,第二个原因是这个工具比较简陋,没有MAT( Eclipse Memory Analyzer tool)、IBM HeapAnalyzer这些专业和强大。
命令格式:jhat file
使用样例:
-
F:\Java\jdk\jdk1.7.0_60\bin>jmap -dump:format=b,file=eclipse.bin
25592
-
Dumping heap to F:\Java\jdk\jdk1.7.0_60\bin\eclipse.bin ...
-
Heap dump file created
-
导出快照完成、之后开始==解析快照:
-
F:\Java\jdk\jdk1.7.0_60\bin>jhat eclipse.bin
-
Reading from eclipse.bin...
-
Dump file created Sat Oct
14
15:
04:
41 CST
2017
-
Snapshot read, resolving...
-
Resolving
555500 objects...
-
WARNING: Failed to resolve object id
0x73e54f1e8
for field constantPoolOop (sig
-
nature L)
-
WARNING: Failed to resolve object id 0x73e54f1e8 for field constantPoolOop (sig
-
nature L)
-
WARNING: Failed to resolve object id 0x73e54f1e8 for field constantPoolOop (sig
-
nature L)
-
WARNING: Failed to resolve object id 0x73e54f1e8 for field constantPoolOop (sig
-
nature L)
-
WARNING: Failed to resolve object id 0x73e54f1e8 for field constantPoolOop (sig
-
nature L)
-
WARNING: Failed to resolve object id 0x73e54f1e8 for field constantPoolOop (sig
-
nature L)
-
WARNING: Failed to resolve object id 0x73e54f1e8 for field constantPoolOop (sig
-
nature L)
-
WARNING: Failed to resolve object id 0x73e54f1e8 for field constantPoolOop (sig
-
nature L)
-
WARNING: Failed to resolve object id 0x73e54f1e8 for field constantPoolOop (sig
-
nature L)
-
WARNING: Failed to resolve object id 0x73e54f1e8 for field constantPoolOop (sig
-
nature L)
-
WARNING: Failed to resolve object id 0x73e54e088 for field constantPoolOop (sig
-
nature L)
-
WARNING: Failed to resolve object id 0x73e54e088 for field constantPoolOop (sig
-
nature L)
-
WARNING: Failed to resolve object id 0x73e54e088 for field constantPoolOop (sig
-
nature L)
-
WARNING: Failed to resolve object id 0x73e54e088 for field constantPoolOop (sig
-
nature L)
-
WARNING: Failed to resolve object id 0x73e54e088 for field constantPoolOop (sig
-
nature L)
-
WARNING: Failed to resolve object id 0x73e54e088 for field constantPoolOop (sig
-
nature L)
-
WARNING: Failed to resolve object id 0x73e54e088 for field constantPoolOop (sig
-
nature L)
-
WARNING: Failed to resolve object id 0x73e54e088 for field constantPoolOop (sig
-
nature L)
-
Chasing references, expect 111 dots.............................................
-
..................................................................
-
Eliminating duplicate references................................................
-
...............................................................
-
Snapshot resolved.
-
Started HTTP server on port 7000
-
Server is ready.
-
载在浏览器中输入localhost:7000查看结果(我是没看懂哈哈)ctrl+c结束解析
注意:如果有其它工具可以分析,否则不建议使用jhat。首先,一般不会直接在生产环境直接分析dump文件,因为分析dump文件是一件耗时耗资源的事情,条件允许的话首选图形分析工具(后面会介绍);其次是jhat的分析功能过于简陋。
2.6 jstack:Java堆栈跟踪工具
jstack(Stack Trace for Java)命令用于生产虚拟机当前时刻的线程快照(一般称为threaddump或者javacore文件)。线程快照就是当虚拟机内每一条线程正在执行的方法堆栈集合,生产线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致长时间等待等都是导致线程长时间停顿的常见原因。线程出现停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做些什么事情,或者等待着什么资源。
jstack命令格式:jstack [option] vmid
option选择的合法值域具有含有请看下表:
jstack执行样例:
F:\Java\jdk\jdk1.7.0_60\bin>jstack -l 25592
-
Full thread dump Java HotSpot(TM) Server VM (20.45-b01 mixed mode):
-
-
"Attach Listener" daemon prio=
10 tid=
0x0852b000 nid=
0x1103 waiting on condition [
0x00000000]
-
java.lang.Thread.State: RUNNABLE
-
-
Locked ownable synchronizers:
-
- None
-
......
-
......
-
......
-
"main" prio=
10 tid=
0x08058400 nid=
0xf06 runnable [
0xf6940000]
-
java.lang.Thread.State: RUNNABLE
-
at java.net.PlainSocketImpl.socketAccept(Native Method)
-
at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:
408)
-
- locked <
0xea12b248> (a java.net.SocksSocketImpl)
-
at java.net.ServerSocket.implAccept(ServerSocket.java:
462)
-
at java.net.ServerSocket.accept(ServerSocket.java:
430)
-
at org.apache.catalina.core.StandardServer.await(StandardServer.java:
430)
-
at org.apache.catalina.startup.Catalina.await(Catalina.java:
676)
-
at org.apache.catalina.startup.Catalina.start(Catalina.java:
628)
-
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
-
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:
39)
-
at
...省略一大部分
2.7 HSDIS:JIT生成代码反汇编
由于本人没有学习过汇编,所以在此章节部分的汇编内容看不懂,所以在这里也只简单介绍一下这个虚拟机插件的大概使用,后续本人学习了汇编语言后有机会再写相关的学习资料。
HSDIS是一个Sun官方推荐的HotSpot虚拟机JIT编译代码的反汇编插件。在这先插两句对JIT的简单描述,JIT是讲.class字节码翻译成本机的机器代码(就是0和1),至于为什么这么做,肯定是提高效率,更多JIT知识可自行学习。 而HSDIS就是把这些被JIT翻译过的机器码(0和1)反编译为汇编(面向IT人员的开发语言)。为什么要无端端把机器语言翻译会开发人员看得懂的汇编语言,是因为当我们需要检查程序性能的时候,希望更能接近计算机语言的本质去分析,由于汇编是直接面向硬件的,而机器语言我们又看不懂,所以最接近本质的还是汇编语言。当然,我们可以基于字节码(.class)层面上进行分析,但随着技术的发展,这些字节码指令的执行过程等细节与虚拟机规范所描述的相差越来越远,就是字节码的行为跟机器码的行为有可能差异很大。所以通过汇编语言分析可以更接近计算机语言的本质。
这个HSDIS JIT反汇编插件包含在HotSpot虚拟机的源码之中,但没有提供编译后的程序。在Project Kenai的网站也可以下载到单独的源码。它的作用是让HotSpot的-XX:PrintAssembly指令调用它来把动态生成的本地代码还原为汇编代码输出,同时还生成了大量有价值的注释,这样我们就可以通过输出代码来分析问题。读者可以根据自己的操作系统和CPU类型从Project Kenai的网站上下载编译好的插件,直接放到JDK_HOME/jre/bin/client和JDK_HOME/jre/bin/server目录中即可。如果没有找到所需操作系统的成品,那就得自己使用源码编译一下。
3 jvm工具之jdk的可视化工具
JDK中除了提供大量的命令行工具外,还有两个功能强大的可视化工具:JConsole和VisualVM,这两个工具是JDK的正式成员。
3.1 JConsole:Java监视与管理控制台
JConsole(Java Monitoring and Management Console)是一种基于JMX的可视化监视、管理工具。它管理部分的功能是针对JMX Mbean进行管理。
知识扩展:JMX(Java Management Extensions)即ava管理扩展,MBean(managed beans)即被管理的Beans。一个MBean是一个被管理的Java对象,有点类似于JavaBean,一个设备、一个应用或者任何资源都可以被表示为MBean,MBean会暴露一个接口对外,这个接口可以读取或者写入一些对象中的属性。
启动:
通过JDK_HOME/bin目录下的“jconsole.exe”启动JConsole后,讲自动搜索出本机运行的所有虚拟机进程,不需要用户自己再用JPS来查询了。也可以使用下面的“远程进程”功能来连接远程服务器,对远程虚拟机进行监控,若连接远程虚拟机,需要开启JMX服务才能连接。如下图所示:
下图为进入JConsole的主页:
概述”页签显示的是整个虚拟机主要运行数据的概览,其中包括“堆内存使用情况”、“线程”、“类”、“CPU使用情况”4种信息的曲线图,这些曲线图是后面“内存”、“线程”、“类”页签的信息汇总。其它详细的页签都不加以说明,自行学习吧,或者后期有充足的时间在详解一下。
3.2 VisualVM:多合一故障处理工具
VisualVM(ALL-in-One Java Troubleshooting Tool)是到目前为止随JDK发布的功能最强大的运行监控和故障处理程序,并且可以预见在未来的一段时间内都是官方主力发展的虚拟机故障处理工具。VisuaVM是基于NetBean平台开发的,因此它一开始就具备了插件扩展功能的特性,通过插件扩展支持,VisualVM几乎可以做到所欲命令行工具的功能和其它Plugins的无限可能性。
作用(functions)
1)显示虚拟机进程以及进程的配置,环境信息(jps,jinfo);
2)监视应用程序的CPU, GC, 堆, 方法区以及线程的信息(jstat、jstack);
3)dump 以及分析堆转储快照(jmap,jhat);
4)方法级的程序运行性能分析,找出被调用最多,运行时间最长的方法;
5)离线程序快照,收集程序的运行时配置,线程dump,内存dump 等信息建立一个快照,可以将快照发送开发者处进行bug 反馈;
6)其他plugins 的无限可能性;(在对应用程序进行检测时,还需要加载相应的插件);
下图为进入VisualVM的主页:
VisualVM 主要特性的兼容性列表:
首次启动VisualVM后,读者先不必着急找应用程序进行监控,因为现在VisualVM还没有加载任何插件,虽然基本的监控、线程面板的功能主程序都以默认插件的形式提供了,但是不给VisualVM装任何扩展插件,就相当于放弃了它最精华的功能,和没有安装任何应用软件的操作系统差不多。
插件可以进行手工安装,在相关网站上下载*.nbm包后,点击“工具—插件—已下载”菜单,然后在弹出的对话框中指定nbm包枯井变可以进行安装,插件安装后存放在JDK_HOME/lib/visualvm/visualvm中。当然同样可以在有网络连接的环境下选择自动安装,点击“工具—插件—可用插件”弹出如下图所示的插件页签中选择合适的插件安装即可。
从VisualVM主页的左菜单栏可以看到,显示的虚拟机进程跟JConsole显示的是一样的,还有一个远程虚拟机进程。当我点击进入一个虚拟机进程后的进程主页如以下所示(不同版本可以会有所差异):
虚拟机进程主页包含了“概述”、“监视”、“抽样器”、“Visual GC”页签,其中“Visual GC”是我自己安装的插件,更详细的VisualVM使用说明就不多说了。后期学习在继续详细解释。
4、总结:
jdk提供的vm故障处理工具都比较实用,常用的jps,jstat,jmap,jstack以及可视化工具visualvm,当然根据个人实际实用情况,可能还选用第三方的工具进行dump分析,如eclipse的MAT(Memory Analyzer Tool)等。灵活实用这些工具,可以给处理问题带来很大的便利。
最终:要知道出现什么问题了考虑使用什么工具。其它的就看你的经验吧。