2.jps(Java Process Status):查看正在运行的Java进程
基本情况:
显示指定系统内所有的HotSpot虚拟机进程(查看虚拟机进程信息),用于查询正在运行的虚拟机进程。
说明:对于本地虚拟机进程来说,进程的本地虚拟机ID与操作系统的进程ID是一致的,是唯一的。
基本语法:jps [options] [hostid]
我们可以通过追加参数,来打印额外的信息。
options参数
-q:仅仅显示LVMID(local virtual machine id),即本地虚拟机唯一id。不显示主类的名称等。
-l:输出应用程序主类的全类名,如果执行的是jar包,则输出jar完整路径。
-m:输出虚拟机进程启动时传递给主类main()的参数。
-v:列出虚拟机进程启动时的JVM参数。比如:-Xms20m -Xmx50m是启动程序指定的jvm参数。
说明:以上参数均可综合使用。
补充:
如果某Java进程关闭了默认开启的UsePerfData参数(即使用参数-XX:-UsePerfData),那么jps命令(以及下面介绍的jstat)将无法探知该Java进程
hostid参数
RMI注册表中注册的主机名。
如果想要远程监控主机上的Java程序,需要安装jstatd。
对于具有更严格的安全事件的网络场所而言,可能使用一个自定义的策略文件来显示对特定的可信主机或网络的访问,尽管这种技术容易收到IP地址欺诈攻击。
如果安全问题无法使用一个定制的策略文件来处理,那么最安全的操作是不运行jstatd服务器,而是在本地使用jstat和jps工具。
3-jstat(JVM Statistics Monitoring Tool):查看JVM统计信息
基本情况:
jstat是一种用于监视虚拟机各种运行状态信息的命令行工具。它可以显示本地或远程虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据。
在没有GUI图形界面,只提供了纯文本控制台环境的服务器上,它将是运行期定位虚拟机性能问题的首选工具。常用语检测垃圾回收问题以及内存泄露问题。
基本语法:jstat -<option> [-t] [-h<lines>] <vmid> [<interval>] [<count>]
查看命令相关参数:jstat -h 或 jstat -help
option参数:
选项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编译的方法。
interval(间隔)参数:
用于指定输出统计数据的周期,单位为毫秒。即:查询间隔。
count参数:
用于指定查询的总次数。
-t参数:
可以在输出信息前加上一个Timestamp列,显示程序的运行时间。单位:秒。
经验:我们可以比较Java进程的启动时间以及总GC时间(GCT列),或者两次测量的时间间隔以及总GC时间的增量,来得出GC时间占运行时间的比例。如果该比例超过20%,则说明目前堆的压力比较大;如果该比例超过90%,则说明堆里几乎没有可用空间,随时都有可能抛出OOM异常。
-h参数:
可以在周期性数据输出时,输出多少行数据后输出一个表头信息。
补充:
jstat还可以用来判断是否出现内存泄露:
第一步:在长时间运行的Java程序中,我们可以运行jstat命令连续多次获取性能数据,并取这几行数据中OU列(即已占用的老年代的内存)的最小值。
第二步:我们每隔一段时间时间重复一次上述操作,来获得多组OU最小值。如果这些值呈上涨趋势,则说明该Java程序的老年代内存已使用量在不断上涨,这意味着无法回收的对象在不断增加,因此很有可能发生内存泄露。
4.-jinfo(Configuration(配置) Info for Java):实时查看和修改JVM配置参数
基本情况:
查看虚拟机配置参数信息,也可用于调整虚拟机的配置参数。
很多情况下,Java应用程序不会指定所有的JVM参数。而此时开发人员可能不知道在某一个具体的Java虚拟机参数的默认值。在这种情况下,可能需要通过查找文档获取某个参数的默认值。这个查找过程可能是非常艰难的。但有了jinfo工具,开发人员可以很方便地找到Java虚拟机参数的当前值。
基本语法:
查看:
jinfo -sysprops PID:可查看由System.getProperties()取得的参数。
jinfo -flags PID:查看曾经赋过值的一些参数。
jinfo -flags 具体参数 PID:查看某个java进程的具体参数的值。
修改:jinfo可以在运行时修改部分参数,并使之立即生效。但是并非所有的参数都支持动态修改。参数只有被标志为manageable的flag可以被实时修改。这个修改能力是及其有限的。
查看被标记为manageable的参数:java -XX:+PrintFlagsFinal -version | grep manageable
针对boolean类型:jinfo -flag [+|-]具体参数 PID。
针对非boolean类型:jinfo -flag 具体参数=具体参数值 PID。
拓展:
java -XX:+PrintFlagsInitial 查看所有JVM参数启动时的初始值
java -XX:+PrintFlagsFinal 查看所有JVM参数的最终值
java -XX:+PrintCommandLineFlags 查看那些已经被用户或者JVM设置过的详细的XX参数的名称和值
5.-jmap(JVM Memory Map):导出内存映像文件和内存使用情况
基本情况:
作用一方面是获取dump文件(堆转储快照文件,二进制文件),它还可以获取目标Java进程的内存相关信息,包括Java堆个区域的使用情况、堆中对象的统计信息、类加载信息等。
开发人员可以在控制台中输入命令“jmap -help”查阅jmap工具的具体使用方式和一些标准选项配置。
基本语法:
- jmap [option] <pid>
- jmap [option] <executable> <core>
- jmap [option] [server_id@]<remote server IP or hostname>
option包括以下这些:(这些参数和Linux下输入显示的命令多少会有不同,包括也受jdk版本的影响)
-dump:生成Java堆转储快照:dump文件
特别的:-dump:live只保存堆中的存活对象
-heap:输出整个对空间的详细信息,包括GC的使用、堆配置信息,以及内存的使用信息等
-histo:输出堆中对象的统计信息,包括类、实例数量和合计容量
特别的:-histo:live只统计堆中的存活对象
-permstat:以ClassLoader为统计口径输出永久代的内存状态信息
仅Linux、solaris平台有效
-finalizerinfo:显示在F-Queue中等待Finalizer线程执行Finalize方法的对象
仅Linux、solaris平台有效
-F:当虚拟机进程对-dump选项没有任何响应时,可使用此选项强制执行生成dump文件
仅Linux、solaris平台有效
-h | help:jmap工具使用的帮助命令
-J <flag>:传递参数给jmap启动的jvm
使用1:导出内存映像文件
一般来说,使用jmap指令生成dump文件的操作算得上是最常用的jmap命令之一,将堆中所有的存活对象导出至一个文件之中。
Heap Dump又叫做堆存储文件,指一个Java进程在某个时间点的内存快照。Heap Dump在触发内存快照的时候会保存此刻的信息如下:
All Objects:Class,fields, primitive(原始) values and references
All Classes:ClassLoader,name, super class, static fields
Garbage Collection Roots:Objects defined to be reachable by the JVM
Thread Stacks and Local Variables: The call-stacks of threads at the moment of the snapshot,and per-frame information about local objects
说明:1、通常在写Heap Dump文件前会触发一次Full GC,所以heap dump文件里保存的都是FullGC后留下的对象信息。
2、由于生成dump文件的比较耗时,因此大家需要耐心等待,尤其是大内存镜像生成dump文件则需要耗费更长的时间来完成。
手动的方式:jmap -dump:format=b, file=<filename.hprof> <pid>
jmap -dump:live,format=b, file=<filename.hprof> <pid>
由于jmap将访问堆中的所有对象,为了保证在此过程中不被应用线程干扰,jmap需要借助安全点机制,让所有的线程停留在不改变堆中数据的状态。也就是说,有jmap导出的堆快照必定是安全点位置的。这可能导致基于该堆快照的分析结果存在偏差。举个例子:假设在编译生成的机器码中,某些对象的生命周期在两个安全点之间,那么:live选项将无法探知到这些对象。另外,如果某个线程长时间无法到达安全点,jmap将一直等下去。这与前面讲的jstat不同,垃圾回收期会主动将jstat所需要的摘要数据保存到固定位置之中,而jstat只需要直接读取即可。
自动的方式:-XX:+HeapDumpOnOutOfMemoryError
-XX: HeapDumpPath = <filename.hprof>
自动的方式:当程序发生OOM退出系统时,一些瞬时信息都随着程序的终止而消失,而重现OOM问题往往比较困难或者耗时。此时如能在OOM时,自动导出dump文件就显得非常迫切。一种比较常用的取得堆快照文件的方法,即使用:-XX:+HeapDumpOnOutOfMemoryError:在程序发生OOM时,导出应用程序的当前堆快照。 -XX: HeapDumpPath :可以指定堆快照的保存位置。
比如:-Xmx100m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:\m.hprof
使用2:显示堆内存相关信息
jmap -heap pid
jmap -histo pid
使用3:其他作用
jmap -permstat pid:查看系统的ClassLoader信息
jmap -Finalizerinfo:查看堆积在Finalizer队列中的对象
6.-jhat(JVM Heap Analysis(分析) Tool):JDK自带堆分析工具
基本情况:Sun JDK提供的 jhat命令与jmap命令搭配使用,用于分析jmap生成的heap dump文件(堆转储快照)。jhat内置了一个微型的HTTP/HTML服务器,生成dump文件的分析结果后,用户可以在浏览器中查看分析结果(分析虚拟机转储快照信息)。
使用了jhat命令,就启动了一个http服务,端口是7000,即http://localhost:7000/,就可以在浏览器里分析。
说明:jhat命令在JDK9、JDK10已经被删除,官方建议用VisualVM来代替。
基本语法:
option参数:
-stack false|true:关闭|打开对象分配调用栈跟踪
-refs false|true:关闭|打开对象引用跟踪
-port port-number:设置jhat HTTP Server的端口号,默认为7000
-exclude exclude-file:执行对象查询时需要排除的数据成员
-baseline exclude-file:指定一个基准堆转储
-debug int:设置debug级别
-version:启动后显示版本信息就退出
-J <flag>:传入启动参数,比如-J -Xmx512m
7.-jstack:打印JVM中线程快照
基本情况:
jstack(JVM Stack Trace(追踪)):用于生成虚拟机指定进程当前时刻的线程快照(虚拟机堆栈跟踪)。线程快照就是当前虚拟机内指定进程的每一条线程正在执行的方法堆栈的集合。
生成快照的作用:可用于定位线程出现长时间停顿的原因,比如线程间死锁、死循环、请求外部资源导致的长时间等待等问题。这些都是导致线程长时间停顿的常见原因。当线程出现停顿时,就可以用jstack显示各个线程调用的堆栈情况。
在thread dump中,要留意下面几种状态
- 死锁,Deadlock(重点关注)
- 等待资源,Waiting on condition(重点关注)
- 等待获取监视器,Waiting on monitor entry(重点关注)
- 阻塞,Blocked(重点关注)
- 执行中,Runable
- 暂停,Suspended
基本语法:
option参数:
-F:当正常输出的请求不被响应时,强制输出线程堆栈
-l:除堆栈外,显示关于锁的附加信息
-m:如果调用到本地方法的话,可以显示C/C++的堆栈
-h:帮助操作
8.-jcmd:多功能命令行
基本情况:
在JDK 1.7以后,新增了一个命令行工具jcmd。它是一个多功能的工具,可用来实现前面除了jstat之外的所有命令的功能。比如:用它来导出堆、内存使用、查看Java进程、导出线程信息、执行GC、JVM运行时间等。
jcmd拥有jmap的大部分功能,并且在Oracle官网上也推荐使用jcmd命令代替jmap命令。
基本语法:
jcmd -I:列出所有的JVM进程
jcmd pid help:针对指定的进程, 列出支持的所有命令
jcmd pid 具体命令:显示指定进程的指定命令的数据
9.-jstatd:远程主机信息收集
之前的指令只涉及到监控本机的Java应用程序,而在这些工具中,一些监控工具也支持对远程计算机的监控(如jps、jstat)。为了启用远程监控,则需要配合使用jstatd工具。
命令jstatd是一个RMI服务端程序,它的作用相当于代理服务器,建立本地计算机与远程监控工具的通信。jstatd服务器将本机的Java应用程序信息传递到远程服务器。