最近读书心得:大道至简,知行合一。利己者存,利他者久。
按计划,分享整理10篇核心基础相关文章,帮助大家知识巩固。虽然理论有点枯燥,但是基础不牢地动山摇大家都懂,还是那句话,磨刀不误砍柴工,好事多磨。大家耐心继续看下去,一定会有收获,不敢说吊打面试官,至少跳槽面试,一旦涉及JVM知识,认真耐心看完全系列文章的同学,成功斩获offer几率一定会大幅提升。
今天的主角调优监控命令,已经是非常贴合生产实战,现在打好基础,等系列第11篇,就开始针对实际案例,带大家应用工具命令解决实际问题。包含jps、jinfo、jstat、jstack、jmap、jhat命令应用示例,以及Arthas、GCeasy、MAT、GCViewer等工具应用介绍。
一、JDK自带工具命令
1.1 jps-查找JVM进程ID
jps命令英文全称:java Virtual Machine Process Status Tool。
查看jps命令可选参数有哪些,和shell命令一样,都是加-help 就可以看到参数列表。
jps :列出Java程序进程ID和Main函数名称
jps -q :只输出进程ID
jps -m :输出传递给JVM的参数
jps -l :输出main函数的完整路径
jps -v :显示传递给JVM的参数
日常最常用就是,用jps -l、以及jps -v去查看jvm的进程ID,以及查看相关进程显示指定设置的jvm参数。
1.2 jinfo-查看并修改JVM运行参数
jinfo英文全称:Java Configuration Info。
jinfo可以用来查看正在运行的Java程序的扩展参数,甚至支持修改运行过程中的部分参数【对运维直接改线上服务比较友好】。比如:
jinfo可选参数:
-flag 打印指定J VM 参数
-flag [+|-] 打开或关闭JVM参数
-flag = 设置指定JVM参数值
-flags 打印JVM 参数
1.3 jstat-查看GC统计信息
jstat命令英文全称:JVM Statistics Monitoring Tool。
jstat可以查看Java程序运行时堆信息的相关情况。
jstat 主要参数如下:
-gc:显示与GC相关信息
-gccapacity:显示各个代的容量和使用情况
-gcnew:显示新生代信息
-gcnewcapacity:显示新生代大小和使用情况
-gcold:显示老年代信息
-gcoldcapacity:显示老年代大小
-gcutil:显示垃圾收集信息
-gccause:显示垃圾收集相关信息(同-gcutil),同时显示最后一次或当前正在发生的垃圾收集的诱发原因
-class:显示ClassLoader的相关信息
-compiler:显示JIT编译的相关信息
1.3.1 jstat -gc 采样GC情况
我们通过-gc命令,可以轻松查看jvm进程当前内存区域使用情况,以及GC详细信息。比如:
# 进程ID 是8 ,采样间隔2s,采样数3 jstat -gc 8 2000 3
jstat gc各个输出字段含义:
S0C:年轻代中S0区的容量 (单位kb)
S1C:年轻代中S1区的容量 (单位kb)
S0U :年轻代中S0区目前已使用空间 (单位kb)
S1U :年轻代中S1区目前已使用空间 (单位kb)
EC :年轻代中Eden的容量 (单位kb)
EU :年轻代中Eden目前已使用空间 (单位kb)
OC :Old代的容量 (单位kb)
OU :Old代目前已使用空间 (单位kb)
MC:metaspace的容量 (单位kb)
MU:metaspace目前已使用空间 (单位kb)
CCSC:压缩类空间大小
CCSU:压缩类空间使用大小
YGC :从JVM启动到采样时年轻代中gc次数
YGCT :从JVM启动到采样时年轻代中gc所用时间(s)
FGC :从JVM启动到采样时old代(全gc)gc次数
FGCT :从JVM启动到采样时old代(全gc)gc所用时间(s)
GCT:从JVM启动到采样时gc用的总时间(s)
如果要单独查看老年代GC情况,可以通过-gcold来查询,比如:
# 进程ID 是8 ,采样间隔2s,采样数3 jstat -gcold 8 2s 3
单独查看老年代GC情况。
1.3.2 jstat -gcutil 查看gc统计信息
# 进程ID 是8 ,采样间隔2s,采样数3 jstat -gcutil 8 2s 3
输出各个字段含义:
S0 年轻代中S0区已使用的占当前容量百分比
S1 年轻代中S1区已使用的占当前容量百分比
E 年轻代中Eden已使用的占当前容量百分比
O 老年代已使用的占当前容量百分比
M metaspace已使用的占当前容量百分比
CCS 压缩使用比例
YGC 从JVM启动到采样时年轻代中gc次数
YGCT 从JVM启动到采样时年轻代中gc所用时间(s)
FGC 从JVM启动到采样时old代(全gc)gc次数
FGCT 从JVM启动到采样时old代(全gc)gc所用时间(s)
GCT 从JVM启动到采样时gc用的总时间(s)
1.4 jstack-线程死锁检测、接口卡顿问题排查
jstack英文全称:Java Stack Trace。
jstack可以很方便查看JVM里当前运行的线程信息,以及生成线程堆栈快照,用于分析是否有死锁、线程执行情况、接口卡顿等问题。
jstack 常用参数:
jstack [ option ] pid 查看指定JVM进程的线程堆栈信息。
jstack [ option ] pid > 文件 将指定进程线程栈信息dump出来写入到指定文件中。
1.4.1 查看JVM进程线程栈信息
通过jstack pid命令,查看某个JVM进程当前运行线程栈全部信息。
也可以通过>指定对应文件,把线程栈信息先导出文件,然后拿出来分析。
1.4.2 查看当前全部线程状态-排查是否有死锁
通过jstack -l 进程pid | grep 来过滤筛查线程栈信息,轻松查看所有线程状态,重点关注DeadLock死锁,Blocked等待阻塞状态。比如:
jstack -l 8 | grep 'java.lang.Thread.State'
1.5 jmap-把堆内存dump出来分析
jmap英文全称:Java Virtual Machine Memory Map。
jmap用来查看并导出堆内存状况,最好是结合jhat使用,jhat有可视化工具分析很方便。
1.5.1 jmap -heap 查看堆内存信息
jmap -heap -pid 查看堆内存信息。比如最大堆内存,年轻代,老年代,元数据区大小,还有年轻代代的E,S区使用情况。
1.5.2 jmap -dump 导出堆内存信息
通过 -dump参数可以生成堆快照文件,并可以指定以二进制格式。甚至可以指定了live子选项,让堆中只有活动的对象dump出来。堆文件可以通过 jjhat 可视化读取,jhat里具体说,也可以使用MAT等第三方工具分析。
这里必须注意:执行这个命令,应用会暂停执行。所以如果当前堆内存使用比较大,就会导致这个过程比较耗时,请慎用。
命令jmap -dump:format=b,file=myapp-heapdump.hprof 进程pid
1.5.3 jmap -clsstats 查看类加载器信息
比如:
jmap -clstats 8
这个命令执行统计会比较慢。
1.6 jhat 洞悉jvm head堆内存信息
jhat 英文全称:Java Heap Analysis Tool。jhat 命令主要是可以启动一个 web服务,用来可视化分析Java head dump 出来的二进制文件。
Java生成堆文件,可以用1.5 分享使用 jmap -dump 命令获取堆内存信息,以及我们在系统服务启动时候增加-XX:+HeapDumpOnOutOfMemoryError 参数,在发生OOM后,JVM自动dump出当时堆内存数据。
1.6.1 jhat 直接分析具体堆文件
首先,我们用jmap命令dump出堆内存文件。命令:
jmap -dump:format=b,file=myapp-heapdump.hprof 进程pid
然后,应用jhat命令,启动对该hprof堆文件进行分析。
jhat xxx.hprof
jhat的console web地址是http://localhost:7000/,打开界面如下:
在这个界面里,我们可以看到已经加载到堆内存的全部类信息,包含是哪个类加载器加载的,弱引用、静态数据、每个类的子类父类信息。
jhat 启动后 html 页面末尾的Other Queriers主要是指:
All classes including platform:当前堆内存中所有的类信息。
Show all members of the rootset :从根集里的全部对象。
Show instance counts for all classes (including platform/excluding platform):包括或者不包含jdk启动类的所有类实例。
Show heap histogram:堆实例的分布图表。
Show finalizer summary:Finalizer 摘要。
Execute Object Query Language (OQL) query: 支持对象查询语句(OQL)。
二、第三方工具
2.1 Arthas 主流JVM监控诊断利器
arthas官网地址:https://arthas.aliyun.com/,arthas 通过远程连接或者在应用本地机器上,实时查看服务 load、内存、gc、线程的状态信息,并支持在不修改应用代码的情况下,对业务问题进行诊断,包括查看方法调用的出入参、异常,监测方法执行耗时,类加载信息等,大大提升线上问题排查效率。
2.1.1 启动Arthas诊断
在官网下载Arthas到本地后,启动jvm服务后,再启动Arthas诊断进程:
java -jar arthas-boot.jar
然后选择对接JVM进程序号,回车。就可以开始对本jvm进行在线诊断。
2.1.2 查看 dashboard
然后输入dashboard,按回车/enter,会展示当前进程的信息,按ctrl+c可以中断执行。
2.1.3 thread -b查看阻塞线程信息
2.1.4 jad 反编译JVM.class代码
jad的好处在于可以确认线上系统运行的代码是否我们之前打包提交的代码。
2.1.5 watch 实时监控方法返回值等
这个不再赘述过多案例,官网给了非常详细的使用说明,此外还有实时修改logger日志级别、查看jvm信息、trace追踪方法调用耗时等。大家可以参考https://arthas.aliyun.com/doc/quick-start.html。
2.2 GCeasy-GC日志分析
https://gceasy.io/,GC提供在线日志分析,而且免费的,里面有Machine Learning分析GC,但是收费。堆内存数据分析非常高效,几秒内帮你分析并给出GC 、JVM堆优化建议。
2.2.1 设置保存JVM GC日志文件
在JVM启动参数里,新增:
-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:/Users/xxx/projectcode/java-home/myapp-gc.log
比如,我们这里制造一个OOM demo,启动参数为:
-Xms16m -Xmx16m -Xmn8m -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:/Users/xxxx/projectcode/java-home/myapp-gc.log。
OOM Demo代码:
public static void main(String[] args) throws InterruptedException { //循环,让堆内存发生GC while (true) { Demo002JvmShow show = new Demo002JvmShow(); User user = new User("拉丁"); show.paramInt = user.getAge(); } }
发生OOM:
2.2.2 将GC文件上传到GCEasy分析
打开https://gceasy.io/,上传gc日志分析。
2.2.3 GC日志结果分析
gceasy可以从gc日志找到你各个区的内存分配情况,还有GC统计信息,一目了然。
2.4 GCViewer GC日志分析
GCViewer也是一款开源的GC日志分析工具。项目在 github上可以下载[https://github.com/chewiebug/GCViewer],可以非常直观地分析出有待调优改进地方。大家有空可以下载体验一下。
2.5 MAT 内存泄漏分析最佳工具
MAT是Memory Analyzer tool的缩写,也是一个优秀的、功能丰富的可视化内存分析工具,尤其是内存泄露分析表现优异。减少内存消耗分析工具。用MAT主要用于:
1、分析内存泄露,找到无法被回收的垃圾对象。
2、分析OOM原因,是否内存分配不合理,还是其他原因;
3、分析线程栈,线程死锁、阻塞情况;
4、查看对象个数及对象内存占用。
由于篇幅有限,这里不详细展开举例visualVM、GCViewer、MAT应用。主流重点还是应用Arthas、jdk命令就很够用。大家只需要找到一个自己最喜欢的工具和命令集去解决生产监控问题即可。工具不在多,喜欢好用就行。
推荐阅读: