JVM工具
首先,JDK 自带了很多监控工具,都位于 JDK 的 bin 目录下,其中最常用的是 jconsole 和 jvisualvm 这两款视图监控工具。
一、jps(Java Process Status)
用于查看有权访问的虚拟机的进程,并显示他们的进程号
-v:列出虚拟机进程启动时的 JVM 参数。比如:-Xms20m -Xmx50m 是启动程序指定的 jvm 参数
二、jstat(JVM Statistics Monitoring Tool)
可以用来监视 JVM 内存内的各种堆和非堆的大小及其内存使用量、类装载、垃圾收集、JIT 编译等运行数据
jstat - [-t] [-h] [ []]
-gc:显示堆各分区大小、YGC,FGC次数和时长。包括 Eden 区、两个 Survivor 区、老年代、永久代等的容量、已用空间、GC 时间合计等信息
-gccapacity:显示内容与 -gc 基本相同,但输出主要关注 Java 堆各个区域使用到的最大、最小空间
-gcutil:显示内容与 -gc 基本相同,但输出主要关注已使用空间占总空间的百分比
-gccause:与 -gcutil 功能一样,但是会额外输出导致最后一次或当前正在发生的 GC 产生的原因
-gcnew:显示新生代 GC 状况
-gcnewcapacity:显示内容与 -gcnew 基本相同,输出主要关注使用到的最大、最小空间
-geold:显示老年代 GC 状况
-gcoldcapacity:显示内容与 -gcold 基本相同,输出主要关注使用到的最大、最小空间
-gcpermcapacity:显示永久代使用到的最大、最小空间
interval 参数:用于指定输出统计数据的周期,单位为毫秒。即:查询间隔
count 参数:用于指定查询的总次数
OOM案例:比较GC时长(GCT列)占运行市场的比例:
如果该比例超过 20%,则说明目前堆的压力较大;
如果该比例超过 98%,则说明这段时期内几乎一直在GC,堆里几乎没有可用空间,随时都可能抛出 OOM 异常
内存泄露案例
每隔一段较长的时间采样多组 OU(老年代内存量) 的最小值,如果这些最小值在上涨,说明无法回收对象在不断增加,可能是内存泄漏导致的。
在长时间运行的 Java 程序中,我们可以运行 jstat 命令连续获取多行性能数据,并取这几行数据中 OU 列(Old Used,已占用的老年代内存)的最小值
然后,我们每隔一段较长的时间重复一次上述操作,来获得多组 OU 最小值。
如果这些值呈上涨趋势,则说明该 Java 程序的老年代内存已使用量在不断上涨,这意味着无法回收的对象在不断增加,因此很有可能存在内存泄漏(不再使用的对象仍然被引用,导致GC无法回收)
三、jstack(JVM Stack Trace)
用于生成虚拟机指定进程当前时刻的线程快照(虚拟机堆栈跟踪)
参数:
-F 当正常输出的请求不被响应时,强制输出线程堆栈
-l 除堆栈外,显示关于锁的附加信息
线程快照:该进程内每条线程正在执行的方法堆栈的集合。
生成线程快照的作用:可用于定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等问题。
这些都是导致线程长时间停顿的常见原因。当线程出现停顿时,就可以用 jstack 显示各个线程调用的堆栈情况。
在 thread dump 中,要留意下面几种状态
- 死锁,Deadlock(重点关注)
- 等待资源,Waiting on condition(重点关注)
- 等待获取监视器,Waiting on monitor entry(重点关注)
- 阻塞,Blocked(重点关注)
- 执行中,Runnable
- 暂停,Suspended
- 对象等待中,Object.wait() 或 TIMED_WAITING
- 停止,Parked
四、jmap(Memory Map)和jhat(Java Heap Analysis Tool)
jmap:打印出某个 JVM 进程内存内的所有对象的情况,一般用于查看内存占用情况。一般结合jhat使用
使用jmap -histo[:live] pid查看堆内存中的对象数目、大小统计直方图,如果带上live则只统计活对象,
jmap进行dump命令格式 jmap -dump:format=b,file=dumpFileName pid
五、Visual VM
六、jconsole:
一个 GUI 监视工具,可以以图表化的形式显示各种数据,并支持远程连接