JVM实战学习——排查java程序 磁盘IO占用过高、CPU占用过高、内存占用过高(pidstat)
一、排查cpu高占用
1.示例代码
使用以下代码,启动的服务会产生cpu资源大量占用的情况
1)占有大量CPU资源
2)启动类
2.查询项目进程
1)使用 jps 命令查询项目启动的进程
[root]# jps
15539 jar ## 其中15539就是项目进程
1349 -- process information unavailable
15673 Jps
2)或者使用 ps -ef | grep java 同样可以查询进程号
[root]# ps -ef | grep java
## 其中 15539 就是项目进程
root 15539 3982 98 11:26 pts/0 00:03:12 java -jar study-spring-app-1.0-SNAPSHOT.jar
root 16139 6845 0 11:30 pts/2 00:00:00 grep java
3.使用 pidstat 工具查询cpu占用情况
## -p 指定进程号
## 15539 即进程号 紧跟 -p后面
## -t 展示进程下的线程资源占用情况
## 1 每秒刷新1次
## 3 共刷新三次
[root]# pidstat -p 15539 -t 1 3
## 通过查询出的信息可以检测到 线程号:15579 占用了大量的cpu资源,达到99%
Average: TGID TID %usr %system %guest %CPU CPU Command
Average: 15539 - 99.00 0.00 0.00 99.00 - java
----- 中间省略若干线程 ----------
Average: - 15577 0.00 0.00 0.00 0.00 - |__http-nio-8080-A
Average: - 15579 99.00 0.00 0.00 99.00 - |__Thread-2
Average: - 15580 0.00 0.00 0.00 0.00 - |__Thread-3
Average: - 15581 0.00 0.00 0.00 0.00 - |__Thread-4
Average: - 15582 0.00 0.00 0.00 0.00 - |__Thread-5
4. 使用jstack工具打印堆栈信息
## 15539 进程号
## > jstack.text 将堆栈信息打到 jstack.text 文件中
[root]# jstack 15539 > jstack.text
5.根据线程ID(15579),在jstack.text中查询对应的堆栈信息
注意 此处根据 pidstat获取的线程号是 十进制。但是 jstack打印的堆栈信息中的nid是 十六进制,因此需要做一层进制转换,15579转十六进制为3cdb
## 根据3cdb检索堆栈信息,即可找到对应类,及其行数(FullCPUTask.java:15)
"Thread-2" #26 prio=5 os_prio=0 tid=0x00007f8118aa6800 nid=0x3cdb runnable [0x00007f80eadf0000]
java.lang.Thread.State: RUNNABLE
at c_6_1_4.FullCPUTask.run(FullCPUTask.java:15)
at java.lang.Thread.run(Thread.java:748)
二、排查磁盘IO频繁
1.示例代码
使用以下代码,启动的服务会产生磁盘IO频繁的情况
1)磁盘IO频繁程序
2)启动类
2.查询项目进程
1)使用 jps 命令查询项目启动的进程
[root]# jps
4833 jar ## 其中4833就是项目进程
1349 -- process information unavailable
4911 Jps
2)或者使用 ps -ef | grep java 同样可以查询进程号
[root]# ps -ef | grep java
## 其中 4833 就是项目进程
root 4833 3982 96 13:40 pts/0 00:00:40 java -jar study-spring-app-1.0-SNAPSHOT.jar
root 4982 6845 0 13:41 pts/2 00:00:00 grep java
3.使用 pidstat 工具查询磁盘IO频繁情况
## -p 指定进程号
## 4883 即进程号 紧跟 -p后面
## -t 展示进程下的线程资源占用情况
## -d 展示进程下的线程IO占用情况
## 1 每秒刷新1次
## 3 共刷新三次
[root]# pidstat -p 4833 -t -d 1 3
## 通过查询出的信息可以检测到 线程号:4890 占用了大量的磁盘IO
Average: TGID TID kB_rd/s kB_wr/s kB_ccwr/s Command
Average: 4833 - 0.00 848.00 848.00 java
Average: - 4833 0.00 0.00 0.00 |__java
----------- 省略其他不相干线程 -------------
Average: - 4890 0.00 848.00 848.00 |__Thread-2
Average: - 4891 0.00 0.00 0.00 |__Thread-3
Average: - 4892 0.00 0.00 0.00 |__Thread-4
Average: - 4893 0.00 0.00 0.00 |__Thread-5
Average: - 5886 0.00 0.00 0.00 |__Attach
4. 使用jstack工具打印堆栈信息
## 4833 进程号
## > jstack.text 将堆栈信息打到 jstack.text 文件中
[root]# jstack 4833 > jstack.text
5.根据线程ID(4890),在jstack.text中查询对应的堆栈信息
注意 此处根据 pidstat获取的线程号是 十进制。但是 jstack打印的堆栈信息中的nid是 十六进制,因此需要做一层进制转换,4890转十六进制为131a
## 根据3cdb检索堆栈信息,即可找到对应类,及其行数(FullIOTask.java:22)
"Thread-2" #26 prio=5 os_prio=0 tid=0x00007fc554afa000 nid=0x131a runnable [0x00007fc540a3f000]
java.lang.Thread.State: RUNNABLE
at java.io.FileOutputStream.write(Native Method)
at java.io.FileOutputStream.write(FileOutputStream.java:290)
at c_6_1_4.FullIOTask.run(FullIOTask.java:22)
at java.lang.Thread.run(Thread.java:748)