1. JDK常用命令
1.1 jps:虚拟机进程状况工具
jps功能:
和ps
命令类似,可以列出正在运行的虚拟机进程,并显示虚拟机执行主类(Main Class
,main()
函数所在的类)名称和进程ID。
参数含义:
选项 | 作用 |
---|---|
-q | 只输出进程ID,省略主类的名称 |
-m | 输出虚拟机进程启动时传递给主类main()函数的参数 |
-l | 输出主类全名,如果进程执行的是Jar包,输出jar路径 |
-v | 输出虚拟机进程启动时的JVM参数 |
一般使用JPS
直接去获取进程ID。
1.2 jstat:[stæt]
虚拟机统计信息监测工具
jstat功能:
监视JVM执行状态信息的命令行工具。显示本地或者远程JVM的类加载、内存、垃圾回收、JIT编译等运行数据,只提供纯文本在控制台的服务器上。是运行期定位JVM性能问题的首选工具。
我们对jstat -gcutil进行分析:
- S:两个
Survivor
区(S0占0%,S1占4.01%空间); - E:表示
Eden
区,使用了72.19%的空间; - O:表示
Old
区,代表老年代; - M:代表
Permanent
,代表永久代; - YGC、FGC:代表年轻代,老年代
GC
次数; - YGCT、FGCT、GCT:代表年轻代
GC
、老年代GC
和所有GC
的时间。
jstat常用命令
查询单位时间内的GC情况:
jstat -gcutil PID 250 100
,250毫秒输出日志,查询100次,查询这段时间内GC情况。看看是不是频繁Full GC导致系统缓慢
1.3 jinfo:Java配置信息工具
jinfo的功能:
实时地查看和调整虚拟机各项参数。
jinfo命令格式:
jinfo [option] <pid>
可以使用 jinfo -flag name=value
修改一部分运行期可写的虚拟机参数值。
1.4 jmap:java内存映像工具
jamp的功能:
用于生成堆转储快照(一般称为heapdump
或dump
文件)如果不使用jmap命令,
- 可以使用
-XX:+HeapDumpOnOutOfMemoryError
参数,让虚拟机在OOM异常出现后自动生成dump
文件。 - 或者通过
-XX:+HeapDumpOnCtrlBreak
参数,则可以使用[Ctrl]+[Break]
键让虚拟机生成dump文件。 - 或者在Linux系统下通过Kill -3命令发送进程退出信号“吓唬”虚拟机,也能拿到dump文件。
jmap的功能:
- 获取dump文件;
- 查询finalize执行队列;详见JVM那点事-对象的自救计划
- Java堆和永久代的详细信息,比如空间使用率,当前用的哪种收集器。
jmap的常用命令:
jmap -histo:live 【pid】> ab.txt
查询内存中对象占比。
jmap -dump:live,format=b,file=tai.dump pid
生成dump文件
1.5 jstack:[stæk]
java堆栈跟踪工具
jstack的作用:
命令一般用于生成虚拟机当前时刻的线程快照(一般称为threaddump或者javacore文件)
jstack的目的:
生成线程快照的主要目的就是定位线程出现长时间停顿的原因。
jsatck常用命令:
jstack -l 【线程pid】
查询线程堆栈信息。
2. 使用JProfiler工具分析情况
运行很久的系统突然服务很慢,一般是大量请求进行访问,导致:
- 慢查询导致线程阻塞,服务变慢;
- 查询大量“大对象”导致频繁GC,服务变慢;
一般生产环境集成skywalking
来监控服务的各项指标。
将线上环境dump下的hhh.hprof
文件(使用jmap -dump:live,format=b,file=hhh.hprof [pid进程id]
得到)使用JProfiler工具打开:
- 发现存在大量大对象,这是引起频繁GC的原因
- 查看调用栈
- 查看GC Roots
- 根据问题线程去定位代码
定位问题代码时,一般情况下是定位com开头的包,并且从下往上去分析线程调用栈。
问题一:线程CPU占用率100%怎么排查?
1. 出现CPU占用率100%原因
- 业务代码原因,大量线程执行Runnable。
- GC线程频繁执行,此时一般是发生内存泄漏。
2. 排查CPU占用高的命令:
- 定位消耗cpu最高的进程PID;
- 根据PID查出消耗cpu最高的线程号;
- 根据线程号查出对应的java线程,进行处理;
我们我们进一步思考,需要什么命令?
- Linux环境中,使用
top
命令,可以按cpu占用率多少输出PID; - 使用
top -Hp PID
,显示一个进程的线程运行的信息列表。按下[P]
可以得到占有率最高线程的PID; - 将线程PID转换为十六进制的nid;
- 使用
jstack
命令:jstack -l 线程PID> ./文件名
打印出来; - 使用nid定位到问题所在位置。
- 若是GC线程频繁执行导致,那么使用JProfiler进行分析。
如何分析jstack输出的threaddump文件?
- New:当线程对象创建时存在的状态,此时线程不可被执行;
- Runnable:线程处于可运行态,只要得到cpu,就可以执行;
- Running:线程正在执行;
- Waiting:执行join()或者wait()方法后,表示该线程正处于等待状态,等待某个资源或条件产生唤醒自己;
- Timed_Waiting:有时间的等待;
- Blocked:阻塞状态,即进入同步方法中,但是没有获得锁;
- Dead:线程结束;
- Deadlock:表示有死锁;
- Waiting on condition:等待某个资源或条件来唤醒自己。比如线程正在sleep或者IO等待;
- Waiting on monitor entry:在等待获取锁;
- in Object.wait():获取锁之后又执行obj.wait()放弃锁;
小结:
对于jsatck的日志,若是系统运行慢我们要着重关注Blocked
、Waiting on condition
、Waiting on monitor entry
、Deadlock
状态;
若是系统cpu消耗高那么肯定有线程执行死循环,那么需要关注Runnable
状态
问题二:如何排查内存泄露和内存溢出
1. 出现内存溢出的原因?
- 内存中一次性加载的数据量过于庞大,比如一次从数据库获取过多数据。
- 集合对象中有对象的引用,集合在使用完毕之后未清空。
- 代码找那个存在死循环或者过多重复的对象实体。
- JVM启动参数内存值设定过小。
- 调用ThreadLocal对象但是没有
remove()
掉。
2. 排查内存溢出的命令
数据在一段时间内一直不正常,十有八九是内存泄露导致的。
- 使用
jps
找出正在运行的虚拟机进程ID(PID); - 使用
jstat
分析运行时JVM进程状况,使用jstat -gcutil PID 250 100
,250毫秒溢出,查询100次,查询这段时间内GC情况。看看是不是频繁Full GC
导致系统缓慢。 - 使用
jmap
命令,内存映像工具。生成heap dump(dump文件)。 - 使用java heap分析工具——MAT的使用,找出内存占用超出预期的嫌疑对象;
- 分析MAT中的
Histogram
柱状图和Dominator Tree
支配者树,分析嫌疑对象和其他对象的引用关系(GC Roots
路径); - 分析程序源码,找出嫌疑对象数量过多的原因。
推荐阅读
JProfiler for mac版本下载地址:
链接: https://pan.baidu.com/s/1I4vvdBJRkpKEu7AA_1c1Iw 密码: p2gj
注册码:L-J11-Everyone#speedzodiac-327a9wrs5dxvz#463a59