JDK内置工具使用(jps、jstack、jmap、jstat)
jps
-
主要参数
-q 不输出类名、Jar名和传入main方法的参数 -m 输出传入main方法的参数 -l 输出main类或Jar的全限名 -v 输出传入JVM的参数
-
查看简单信息
jps -lm 16163 com.zhangaoo.clockinout.Application 92805 sun.tools.jps.Jps -lm
-
查看详细信息
会把详细的JVM参数等信息都列出来
jps -lvm | grep clockinout 16163 com.zhangaoo.clockinout.Application -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:61210,suspend=y,server=n -XX:TieredStopAtLevel=1 -Xverify:none -Dspring.profiles.active=dev -Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=61209 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=127.0.0.1 -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true -javaagent:/Users/zealzhangz/Library/Caches/IntelliJIdea2018.3/captureAgent/debugger-agent.jar -Dfile.encoding=UTF-8
jstack
jstack
就是查看当前 Java
程序内线程详细堆栈信息的工具
-
主要参数
Options: -F to force a thread dump. Use when jstack <pid> does not respond (process is hung)(强制线程转储,此时线程会被挂起) -m to print both java and native frames (mixed mode)(打印Java和native接口的堆栈信息) -l long listing. Prints additional information about locks(打印关于锁的详细信息,如果有线程死锁可以使用jstack -l pid查看锁或资源的持有信息) -h or -help to print this help message
-
利用 jstack 排除高CPU线程
-
首先利用上面的 jps -ml | grep tale 找到对应的进程如下:
10815 tale-latest.jar --app.env=prod
-
然后使用 top 查看改进程下的所有线程情况
$ top -n 1 -H -p 10815 Tasks: 20 total, 1 running, 19 sleeping, 0 stopped, 0 zombie Cpu(s): 4.3%us, 1.1%sy, 0.0%ni, 94.6%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Mem: 1019988k total, 781700k used, 238288k free, 83848k buffers Swap: 0k total, 0k used, 0k free, 283120k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 10838 zhanga 20 0 2407m 228m 13m R 97.8 23.0 22:57.07 java 10815 zhanga 20 0 2407m 228m 13m S 0.0 23.0 0:00.00 java # 同时用 jstack 记录堆栈信息 $ jstack 10815 > jstack-output.txt
观察到 10838 的线程几乎占用了所有CPU,将线程ID转化为16进制,因为jstack使用16进制表示
$ printf "%x\n" 10838 2a56
然后到刚刚记录的堆栈信息搜索
2a56
,发现如下堆栈信息:"worker@threadㄧ1" #18 prio=5 os_prio=0 tid=0x00007fd8d4009000 nid=0x2a56 runnable [0x00007fd8dd284000] java.lang.Thread.State: RUNNABLE at java.util.regex.Pattern$BnM.match(Pattern.java:5464) at java.util.regex.Matcher.search(Matcher.java:1248) at java.util.regex.Matcher.find(Matcher.java:637) at java.util.regex.Matcher.replaceAll(Matcher.java:951) at java.lang.String.replace(String.java:2240) at com.vdurmont.emoji.EmojiParser.parseToUnicode(EmojiParser.java:129) at com.tale.extension.Commons.emoji(Commons.java:240) at com.tale.utils.TaleUtils.mdToHtml(TaleUtils.java:170) at com.tale.extension.Theme.intro(Theme.java:299) at com.tale.extension.Theme.intro(Theme.java:281) at sun.reflect.GeneratedMethodAccessor108.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
- 分析如上调用堆栈,发现正则匹配相关逻辑,很可疑
- 定位到源码
com.tale.utils.TaleUtils.mdToHtml
这个方法,从名字可知是Markdown
转HTML
的功能,通过测试发现 mdToHtml方法执行需要花很长时间,至此就找到了出问题的源头,可以优化mdToHtml方法,或者使用缓存来缓解这种情况
-
如果有其他问题,比如死锁等也可以使用此办法了排除,值得关注的线程状态有:
- 死锁:Deadlock(重点关注)
- 执行中:Runnable
- 等待资源:Waiting on condition(重点关注)
- 等待获取监视器:Waiting on monitor entry(重点关注)
- 暂停:Suspended
- 对象等待中:Object.wait() 或 TIMED_WAITING
- 阻塞:Blocked(重点关注)
- 停止:Parked
-
jmap
jmap
命令可以获得运行中的 jvm
的堆的快照,从而可以离线分析堆,以检查内存泄漏,检查一些严重影响性能的大对象的创建,检查系统中什么对象最多,各种对象所占内存的大小等等。
打印heap的概要信息
jmap -heap PID
查看堆内存中的对象数目、大小
$ jmap -histo:live 19931 | less
内存dump文件
$ jhat -port 9998 文件名.dump
该命令通常用来分析内存泄漏OOM,通常做法是:
- 使用 JVM 参数获取 dump 文件
- 进入Tomcat的'bin'目录,在'catalina.sh'文件里添加如下内容
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=c:\jakarta-tomcat\webapps
- 然后使用MAT分析工具,如jhat命令,eclipse的mat插件。
jstat
Jstat
用于查看gc
垃圾回收使用情况:
- 类的加载及卸载情况
- 查看新生代、老生代及持久代的垃圾收集情况,包括垃圾回收的次数及垃圾回收所占用的时间
➜ ~ jstat -help
Usage: jstat -help|-options
jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
- option:我们经常使用的选项有gc、gcutil
- vmid:java进程id
- interval:间隔时间,单位为毫秒
- count:打印次数
Java7以及之前的Heap模型,java8以及之后已经没有Perm了,被Metaspace (元空间)取代:
|<--Minor GC->| |<--------Major GC-------->|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|| | | | | ||
|| Eden |s0|s1| Old Memory | Perm ||
|| | | | | ||
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|<--------------JVM Heap(-Xms -Xmx)----------->| -XX:PermSize
|<-Young Gen(-Xmn)->| -XX:MaxPermSize
-
堆内存 = 年轻代 + 年老代 + 永久代
-
年轻代 = Eden区 + 两个Survivor区(s0和s1)
类加载统计
$ jps -ml | grep clockinout
16163 com.zhangaoo.clockinout.Application
$ jstat -class 16163
Loaded Bytes Unloaded Bytes Time
11413 21630.8 1 1.6 5.08
- Loaded:加载
class
的数量 - Bytes:所占用空间大小
- Unloaded:未加载数量
- Bytes:未加载占用空间
- Time:Time spent performing class load and unload operations
垃圾回收统计
jstat -gc 16163 1000 10
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
8704.0 8704.0 4602.0 0.0 69952.0 54161.4 174784.0 29357.1 24320.0 22719.6 2816.0 2513.7 206 0.719 1 0.043 0.762
8704.0 8704.0 4602.0 0.0 69952.0 54161.4 174784.0 29357.1 24320.0 22719.6 2816.0 2513.7 206 0.719 1 0.043 0.762
8704.0 8704.0 4602.0 0.0 69952.0 54161.4 174784.0 29357.1 24320.0 22719.6 2816.0 2513.7 206 0.719 1 0.043 0.762
8704.0 8704.0 4602.0 0.0 69952.0 54161.4 174784.0 29357.1 24320.0 22719.6 2816.0 2513.7 206 0.719 1 0.043 0.762
8704.0 8704.0 4602.0 0.0 69952.0 54161.4 174784.0 29357.1 24320.0 22719.6 2816.0 2513.7 206 0.719 1 0.043 0.762
8704.0 8704.0 4602.0 0.0 69952.0 54161.4 174784.0 29357.1 24320.0 22719.6 2816.0 2513.7 206 0.719 1 0.043 0.762
8704.0 8704.0 4602.0 0.0 69952.0 54161.4 174784.0 29357.1 24320.0 22719.6 2816.0 2513.7 206 0.719 1 0.043 0.762
8704.0 8704.0 4602.0 0.0 69952.0 54180.3 174784.0 29357.1 24320.0 22719.6 2816.0 2513.7 206 0.719 1 0.043 0.762
8704.0 8704.0 4602.0 0.0 69952.0 54180.3 174784.0 29357.1 24320.0 22719.6 2816.0 2513.7 206 0.719 1 0.043 0.762
8704.0 8704.0 4602.0 0.0 69952.0 54180.3 174784.0 29357.1 24320.0 22719.6 2816.0 2513.7 206 0.719 1 0.043 0.762
- S0C:第一个幸存区的大小
- S1C:第二个幸存区的大小
- S0U:第一个幸存区的使用大小
- S1U:第二个幸存区的使用大小
- EC:伊甸园区的大小
- EU:伊甸园区的使用大小
- OC:老年代大小
- OU:老年代使用大小
- MC:方法区大小
- MU:方法区使用大小
- CCSC:压缩类空间大小
- CCSU:压缩类空间使用大小
- YGC:年轻代垃圾回收次数
- YGCT:年轻代垃圾回收消耗时间
- FGC:老年代垃圾回收次数
- FGCT:老年代垃圾回收消耗时间
- GCT:垃圾回收消耗总时间
堆内存统计
$ jstat -gccapacity 17265
NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC
87360.0 87360.0 87360.0 8704.0 8704.0 69952.0 174784.0 174784.0 174784.0 174784.0 0.0 1071104.0 24320.0 0.0 1048576.0 2816.0 206 1
# 字段解释
NGCMN: Minimum new generation capacity (kB).
NGCMX: Maximum new generation capacity (kB).
NGC: Current new generation capacity (kB).
S0C: Current survivor space 0 capacity (kB).
S1C: Current survivor space 1 capacity (kB).
EC: Current eden space capacity (kB).
OGCMN: Minimum old generation capacity (kB).
OGCMX: Maximum old generation capacity (kB).
OGC: Current old generation capacity (kB).
OC: Current old space capacity (kB).
MCMN: Minimum metaspace capacity (kB).
MCMX: Maximum metaspace capacity (kB).
MC: Metaspace capacity (kB).
CCSMN: Compressed class space minimum capacity (kB).
CCSMX: Compressed class space maximum capacity (kB).
CCSC: Compressed class space capacity (kB).
YGC: Number of young generation GC events.
FGC: Number of full GC events.
垃圾回收概要统计
jstat -gcutil 17265 1000 10
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
52.87 0.00 80.00 16.80 93.42 89.26 206 0.719 1 0.043 0.762
52.87 0.00 80.00 16.80 93.42 89.26 206 0.719 1 0.043 0.762
52.87 0.00 80.00 16.80 93.42 89.26 206 0.719 1 0.043 0.762
52.87 0.00 80.00 16.80 93.42 89.26 206 0.719 1 0.043 0.762
52.87 0.00 80.00 16.80 93.42 89.26 206 0.719 1 0.043 0.762
52.87 0.00 80.00 16.80 93.42 89.26 206 0.719 1 0.043 0.762
52.87 0.00 80.00 16.80 93.42 89.26 206 0.719 1 0.043 0.762
52.87 0.00 80.00 16.80 93.42 89.26 206 0.719 1 0.043 0.762
52.87 0.00 80.00 16.80 93.42 89.26 206 0.719 1 0.043 0.762
52.87 0.00 80.00 16.80 93.42 89.26 206 0.719 1 0.043 0.762
- S0:幸存1区当前使用比例
- S1:幸存2区当前使用比例
- E:伊甸园区使用比例
- O:老年代使用比例
- M:元数据区使用比例
- CCS:压缩使用比例
- YGC:年轻代垃圾回收次数
- FGC:老年代垃圾回收次数
- FGCT:老年代垃圾回收消耗时间
- GCT:垃圾回收消耗总时间
本文由 zealzhangz 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为:
2020/03/20 18:58