《深入理解Java虚拟机》学习笔记之工具

时间:2023-03-08 21:03:59

善于利用工具,不仅可以加快我们分析数据,还可以快速定位和解决问题。现在我们就来看看虚拟机性能监控和故障处理工具。

在JDK的bin目录可以看到sun免费送给了我们很多小工具,这些工具虽然小巧但功能强大且稳定,你看到的小工具其实是lib\tools.jar的快捷方式而已,工具的具体执行是被打包进了tools.jar了。

jps:虚拟机进程状态工具(JVM Process Status Tool)

jps不仅名字像unix的ps命令,其功能与ps也很类似:列出正在运行的虚拟机进程,并显示虚拟机执行主类(main()所在的类)的名字,以及这些进程再本地虚拟机的唯一ID(LVMID,Local Virtual Machine Identifier)。而LVMID和操作下图的PID(Process Identifier)是一致的。如果同时启动了多个虚拟机进程,无法根据进程名称定位时,那就只能依赖jps命令显示主类的功能区分了。命令格式:

usage: jps [-help]
jps [-q] [-mlvV] [<hostid>] Definitions:
<hostid>: <hostname>[:<port>]
  • -q 仅输出LVMID,省略主类的名称;
  • -m 输出虚拟机进程启动时传递给主类main()函数的参数;
  • -l 输出主类的全名,如果进程执行的是jar包,则输出jar的路径;
  • -v 输出虚拟机进程启动时JVM参数;
  • -V 输出通过flag文件传递到JVM中的参数;
  • -Joption 传递参数到JVM,例如:-J-Xms48m;

hostid的格式是:<hostname>[:<port>],port默认是1099,需要服务器启动jstatd服务,否则会提示

RMI Server JStatRemoteHost not available

jstatd命令是一个RMI Server应用程序,提供了对JVM的创建和结束监视,也为远程监视工具提供了一个可以attach的接口。用法

usage: jstatd [-nr] [-p port] [-n rminame]
  • -nr 当一个存在的RMI Registry没有找到时,不尝试创建一个内部的RMI Registry;
  • -p port 端口号,默认为1099;
  • -n rminame 默认为JStatRemoteHost;如果多个jstatd服务开始在同一台主机上,rminame唯一确定一个jstatd服务;
  • -J jvm选项;

在服务器直接启动jstatd会报如下异常

Could not create remote object
access denied (java.util.PropertyPermission java.rmi.server.ignoreSubClasses write)
java.security.AccessControlException: access denied (java.util.PropertyPermission java.rmi.server.ignoreSubClasses write)
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:323)
at java.security.AccessController.checkPermission(AccessController.java:546)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
at java.lang.System.setProperty(System.java:727)
at sun.tools.jstatd.Jstatd.main(Jstatd.java:122)

这是因为没有给jstatd指定安全策略,需要创建安全策略文件,自定义命名为java.all.policy,内容如下:

grant codebase "file:${java.home}/../lib/tools.jar" {
permission java.security.AllPermission;
};

再次启动

jstatd -J-Djava.security.policy=java.all.policy

或使用自定义端口2020

rmiregistry 2020&
jstatd -J-Djava.security.policy=java.all.policy -p 2020

注意要指定java.all.policy文件的路径,而且记得要用root运行哦,不然只能监控到jstatd。
然后可以使用jps连接

jps 10.9.146.201

jps rmi://10.9.146.201:1099

jstat:虚拟机统计信息监视工具(JVM Statistics Monitoring Tool)

Jstat主要用于监控虚拟机的各种运行状态信息,如类的装载、内存、垃圾回收、JIT编译器等,在没有GUI的服务器上,这款工具是首选的一款监控工具。其用法如下:

jstat [option vmid [interval [s|ms] [vount] ] ]

如果是在本地虚拟机进程,vmid与lvmid是一致的,如果是远程虚拟机进程,那么vmid的格式是:[protocol:][//]lvmid[@hostname[:port]/servername]

参数interval和count分别表示查询间隔和查询次数,如每1毫秒查询一次进程20445的垃圾回收情况,监控20次,命令如下所示:

jstat –gc 20445 1 20

选项option代表用户需要查询的虚拟机的信息,主要分为3类:类装载、垃圾回收和运行期的编译情况,具体如下表所示:

  • -class  监视类的装载、卸载数量以及类的装载总空间和耗费时间等
  • -gc  监视Java堆,包含eden、2个survivor区、old区和永久带区域的容量、已用空间、GC时间合计等信息
  • -gccapcity  监视内容与-gc相同,但输出主要关注Java区域用到的最大和最小空间
  • -gcutil  监视内容与-gc相同,但输出主要关注已使用空间占总空间的百分比
  • -gccause  与-gcutil输出信息相同,额外输出导致上次GC产生的原因
  • -gcnew  监控新生代的GC情况
  • -gcnewcapacity  与-gcnew监控信息相同,输出主要关注使用到的最大和最小空间
  • -gcold  监控老生代的GC情况
  • -gcoldcapacity  与-gcold监控信息相同,输出主要关注使用到的最大和最小空间
  • -gcpermcapacity  输出永久带用到的最大和最小空间
  • -compiler  输出JIT编译器编译过的方法、耗时信息
  • -printcompilation  输出已经被JIT编译的方法

jinfo:Java配置信息工具(Configuration Info for Java)

jinfo的作用是实时查看和调整虚拟机的各项参数,但其在windows上好多选项不能用的,用法:

Usage:
jinfo [option] <pid>
(to connect to running process)
jinfo [option] <executable <core>
(to connect to a core file)
jinfo [option] [server_id@]<remote server IP or hostname>
(to connect to remote debug server) where <option> is one of:
-flag <name> to print the value of the named VM flag
-flag [+|-]<name> to enable or disable the named VM flag
-flag <name>=<value> to set the named VM flag to the given value
-flags to print VM flags
-sysprops to print Java system properties
<no option> to print both of the above
-h | -help to print this help message

jmap:Java内存映像工具(Memory Map for Java)
jmap不仅用于生成堆转储快照,还可以查询finalize执行队列、Java堆和永久代的详细信息,如空间使用率、当前用的是哪种收集器等。和jinfo一样,jmap有不少功能在Windows平台下都是受限的。用法

Usage:
jmap [option] <pid>
(to connect to running process)
jmap [option] <executable <core>
(to connect to a core file)
jmap [option] [server_id@]<remote server IP or hostname>
(to connect to remote debug server)

主要选项如下

  • -dump:生成Java堆转储快照。格式为:-dump:[live,] format=b,file=<filename>,其中live子参数说明是否只dump出存活的对象
  • -finalizerinfo:显示在F-Queue中等待Finalizer线程执行finalize方法的对象。只在Linux/Solaris平台下有效。
  • -heap:显示Java堆详细信息,如使用哪种收集器、参数配置、分代状况等。只在Linux/Solaris平台下有效。
  • -histo:显示堆中对象统计信息,包括类、实例数量和合计容量。
  • -permstat:以ClassLoader为统计口径显示永久代内存状态。只在Linux/Solaris平台下有效。
  • -F:当虚拟机进程对-dump选项没有响应时,可以使用这个选项强制生成dump快照。只在Linux/Solaris平台下有效。

jhat:虚拟机堆转储快照分析工具(JVM Heap Analysis Tool)

jhat命令与jmap命令搭配使用,来分析jmap生成的堆存储快照。jhat内置了一个微型的HTTP/HTML服务器,生成dump文件的分析结果后,可以在浏览器中查看。实事求是地说,不过一般不会使用如此简陋的工具来分析dump文件。

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

jstack [ option ] vmid

option选项的合法值与具体含义为:

  • -F : 当正常输出的请求不被响应时,强制输出线程堆栈;
  • -l:除堆栈外,显示关于锁的附加信息;
  • -m:如果调用到本地方法的话,可以显示C/C++的堆栈;

以上都是小工具,还有非常齐全的整合工具如jconsole和VisualVM,都是非常强的工具,而VisualVM是jconsole的增强版,使用VisualVM链接远程也需要启动jstatd服务,具体就不详述了。