一直想部署Java环境测试一下CPU或内存飙升场景,实操问题定位。自己如果部署虚拟机+安装Linux环境+配置java环境,太费劲了。幸好有Docker容器技术,装一个docker desktop,直接下载所需镜像,及省劲又快捷。
下载JDK8的Linux容器镜像环境
docker pull java:8
查看是否下载完成
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
java 8 d23bdf5b1b1b 6 years ago 643MB
由于是一个比较纯净的镜像,没有vim等指令,所以我们将本地Bug代码mount到镜像中,可以很方便的进行测试。
启动镜像并将/Users/xxx/workspaceforjava
本地路径mount到镜像中/root/workspaceforjava
下,/Users/xxx/workspaceforjava`中的本地文件就可以在镜像的/root/workspaceforjava下看到。
docker run -d -it --name java-8 --mount type=bind,source=/Users/xxx/workspaceforjava,target=/root/workspaceforjava java:8
进入镜像中。
docker exec -it java-8 /bin/bash
一段死锁代码
package com.example.demo;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class DemoApplication {
public static void main(String[] args) {
Lock lock1=new ReentrantLock();
//线程t1中
new Thread(()->{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
while (!lock1.tryLock()){
System.out.println("线程1 一直自旋获取锁");
}
System.out.println("线程1 获取到锁 do something");
}).start();
// 线程2
new Thread(()->{
lock1.lock(); //此时线程2 获取到锁 但是一直阻塞 导致锁无法释放
while (true){
}
}).start();
}
}
存放在/Users/xxx/workspaceforjava/dome/demo-start/src/main/com/example/demo/DemoApplication下,也可以不按照这么放置,但在执行时需要带上package包名路径,如下面的指令。
javac -d . DemoApplication.java
java com.example.demo.DemoApplication
通过top
命令,可以看到PID为71的进程CPU使用率达到98.9%。
top - 03:25:33 up 2:07, 0 users, load average: 5.22, 1.64, 0.74
Tasks: 5 total, 1 running, 4 sleeping, 0 stopped, 0 zombie
%Cpu(s): 31.6 us, 63.5 sy, 0.0 ni, 4.6 id, 0.0 wa, 0.0 hi, 0.4 si, 0.0 st
KiB Mem: 4028960 total, 3532528 used, 496432 free, 349412 buffers
KiB Swap: 1048572 total, 0 used, 1048572 free. 2079136 cached Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
71 root 20 0 3354712 45896 16820 S 98.9 1.1 0:44.28 java
1 root 20 0 21948 3328 3024 S 0.0 0.1 0:00.03 bash
使用top -H -n 1 -p 71
可以看到,PID为84和85的占用CPU比较高。
top - 03:25:58 up 2:08, 0 users, load average: 5.57, 2.01, 0.89
Threads: 15 total, 2 running, 13 sleeping, 0 stopped, 0 zombie
%Cpu(s): 3.3 us, 3.0 sy, 0.0 ni, 93.3 id, 0.1 wa, 0.0 hi, 0.2 si, 0.0 st
KiB Mem: 4028960 total, 3537752 used, 491208 free, 349532 buffers
KiB Swap: 1048572 total, 0 used, 1048572 free. 2079456 cached Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
84 root 20 0 3354712 45416 16820 R 34.6 1.1 0:29.71 java
85 root 20 0 3354712 45416 16820 R 23.1 1.1 0:38.58 java
使用jstack -l 71 > ./jstack.log
将jstack信息打印到jstack.log中。将10进制的85转化为16进制后为55,通过cat和grep打印出包括54的后10行信息。
cat ./jstack.log | grep -A 10 "55"
参考: