-
- 打印所有真在运行的Java进程信息,包括:基本的进程ID,主类,-l打印模块及包名,-v打印传递给JVM参数,-m打印传递给主类的参数
-
jps -mlv
-
-
打印目标Java进程的性能数据
-
jstat -gc -t 10000 1s 4 (每一秒跑1次,共跑4次)
-
$ jstat -options -class : 打印类加载相关数据 -compiler :打印即时编译相关数据 -gc :以gc开头的,将打印垃圾回收相关数据 -gccapacity -gccause -gcmetacapacity -gcnew -gcnewcapacity -gcold -gcoldcapacity -gcutil -printcompilation : 打印即时编译相关数据 -t:打印进程运行实际
-
使用不同的垃圾回收器,jstat -gc的结果也有所不同
$ jstat -gc -t 94346 1s
Timestamp | S0C | S1C | S0U | S1U | EC | EU | OC | OU | MC | MU | CCSC | CCSU | YGC | YGCT | FGC | FGCT | CGC | CGCT | GCT |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
2982 | 0 | 10240 | 0 | 10240 | 87040 | 19456 | 164864 | 77213.4 | 37504 | 36272.1 | 4224 | 3861 | 10 | 0.09 | 0 | 0 | 4 | 0.006 | 0.096 |
2982.9 | 0 | 10240 | 0 | 10240 | 87040 | 19456 | 164864 | 77213.4 | 37504 | 36272.1 | 4224 | 3861 | 10 | 0.09 | 0 | 0 | 4 | 0.006 | 0.096 |
2984 | 0 | 10240 | 0 | 10240 | 87040 | 19456 | 164864 | 77213.4 | 37504 | 36272.1 | 4224 | 3861 | 10 | 0.09 | 0 | 0 | 4 | 0.006 | 0.096 |
2985 | 0 | 10240 | 0 | 10240 | 87040 | 19456 | 164864 | 77213.4 | 37504 | 36272.1 | 4224 | 3861 | 10 | 0.09 | 0 | 0 | 4 | 0.006 | 0.096 |
2986 | 0 | 10240 | 0 | 10240 | 87040 | 19456 | 164864 | 77213.4 | 37504 | 36272.1 | 4224 | 3861 | 10 | 0.09 | 0 | 0 | 4 | 0.006 | 0.096 |
2987 | 0 | 10240 | 0 | 10240 | 87040 | 19456 | 164864 | 77213.4 | 37504 | 36272.1 | 4224 | 3861 | 10 | 0.09 | 0 | 0 | 4 | 0.006 | 0.096 |
-
S:Survivor 区 ; E:Eden区 ; O:old区
-
C:Capacity容量 ; U:Utility已使用量
-
我们可比较 Timestamp(进程启动时间) 和 GCT列(总GC时间),来评估当前堆压力,如果比例超过20%,说明当前堆压力较大,如果比例超过90%,说明堆几乎没有可用空间,随时可能抛出OOM异常。
-
CGC:GC Stop-The-World的次数
-
CGCT:GC Stop-The-World的时间
-
OU:老年代使用量,多次取值,如果OU的值呈上涨趋势,说明Java程序老年代内存使用量不断上涨,无法回收的对象不断增加,因此很有可能存在内存泄露。
-
- 分析JVM堆栈对象
- -clstats 打印被加载类的信息
- -finalizerinfo 打印所有待finalize的对象
- -histo 统计各个类的实例数目以及占用内存,并按照内存使用量从多到少的顺序排列,-histo:live只统计堆中存活的对象
- -dump 导出JVM堆的快照,-dump:live 只保存堆中存活对象
常用: jmap -dump:live,format=b,file=filename.bin 这种格式能够被其他GUI工具查看,具体参考后面GUI篇
为了不影响应用线程,jmap需要借助安全点机制,让所有线程停留在不可变化堆中数据的状态
jmap、jinfo、jstack、jcmd依赖JVM的Attach API,只能监控本地Java进程,一旦开启JVM参数 -XX:+DisableAttachMechanism,那么Attach API将无法执行,那么如果你不想被其他进程监控,就需要开启这个参数。
-
- 用来查看目标Java进程的参数(包括:-X、-XX、-D设置的参数)
- jinfo 20111
- 也可用来修改Java进程的 manageable虚拟机参数
- jinfo -flag +HeapDumpAfterFullGC 20111 :开启20111所指定的Java进程的HeapDumpAfterFullGC参数
- 用来查看目标Java进程的参数(包括:-X、-XX、-D设置的参数)
-
- 打印目标Java进程中各个线程的栈轨迹,以及这些线程所持有的锁
-
- 替换前面除了jstat之外的所有命令
- eclipse的MAT工具,可解析上述二进制快照
- MAT获取快照的方式:
- 使用Attach API
- 新建一个虚拟机来运行Attach API
- 使用jmap工具
- 加载快照后,MAT展现一张饼图,其中列举占据的Retained heap最多的几个对象
- Shallow heap:指对象自身所占据的内存
- Retained heap:指当对象不再被引用时,垃圾回收器所能回收的总内存,包括对象自身所占据的内存,以及仅所能够通过该对象引用的其他对象所占据的内存
- 视图:
- histogram:直方图
- dominator tree:支配树
- MAT获取快照的方式:
- JMC:Java Mission Control
- JVM性能监控工具
- GUI有众多收集JVM性能的数据插件,如果JMX Console(访问存储JVM各个子系统运行数据的MXBeans)、JFR(Java Fligt Recorder,JVM内置的高效profiling工具)
- JFR性能开销很小,可用于生产高负荷下,不影响虚拟机优化
- 记录事件:
- 线程事件
- 锁事件
- 新建对象、垃圾回收、即时编译等
- 事件类型:
- 瞬时事件 Instant Event:用户关心的是他们的发生与否,例如异常、线程启动事件
- 持续时间 Duration Event:用户关心的是他们的持续时间,例如垃圾回收事件
- 计时时间 Timed Event:指时长超出指定阀值的持续事件
- 取样时间 Sample Event:指周期取样的事件
- 记录事件:
- JFR在JDK11后,开放
- GCViewer:查看GC日志