1)jps
java命令用于显示java进程
[root@192 bin]# jps -lvm
7181 topjava-1.0-SNAPSHOT.jar
7181:表示进程ID
2) top
查找进程占用cpu信息
top - 19:27:48 up 28 min, 3 users, load average: 0.96, 0.26, 0.19
Tasks: 455 total, 4 running, 451 sleeping, 0 stopped, 0 zombie
%Cpu(s): 37.1 us, 31.3 sy, 0.0 ni, 31.3 id, 0.0 wa, 0.0 hi, 0.2 si, 0.0 st
KiB Mem : 2865552 total, 594388 free, 1422068 used, 849096 buff/cache
KiB Swap: 1953788 total, 1953748 free, 40 used. 1142360 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
7181 root 20 0 1833828 40700 10288 S 49.8 1.4 0:11.52 java
2)top -Hp 7181
7181是上面找到的进程号,此命令可以查看占用高CPU的进程内部具体是哪些线程(TID)在占用CPU,看哪些线程的时间很长
[root@192 bin]# top -Hp 7181
top - 19:31:14 up 31 min, 3 users, load average: 1.86, 1.21, 0.60
Threads: 13 total, 1 running, 12 sleeping, 0 stopped, 0 zombie
%Cpu(s): 31.5 us, 32.0 sy, 0.0 ni, 36.2 id, 0.0 wa, 0.0 hi, 0.3 si, 0.0 st
KiB Mem : 2865552 total, 591560 free, 1421284 used, 852708 buff/cache
KiB Swap: 1953788 total, 1953748 free, 40 used. 1143352 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
7193 root 20 0 1833828 40756 10292 R 50.3 1.4 1:52.48 java
7192 root 20 0 1833828 40756 10292 S 0.7 1.4 0:00.20 java
7181 root 20 0 1833828 40756 10292 S 0.0 1.4 0:00.00 java
发现7193线程占用cpu高
3) printf "%x\n" 7193
将10进制线程ID转换成16进制
[root@192 bin]# printf "%x\n" 7193
1c19
4) jstack 7181 > 7181.log
jstack命令生成的thread dump信息包含JVM中所有存活的线程
根据线程ID:1c19查找文件内容
"testThread" prio=10 tid=0x00007f7464148800 nid=0x1c19 runnable [0x00007f745db00000]
java.lang.Thread.State: RUNNABLE
at java.io.FileOutputStream.writeBytes(Native Method)
at java.io.FileOutputStream.write(FileOutputStream.java:345)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
- locked <0x00000000d4407768> (a java.io.BufferedOutputStream)
at java.io.PrintStream.write(PrintStream.java:482)
- locked <0x00000000d4407748> (a java.io.PrintStream)
at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
at sun.nio.cs.StreamEncoder.flushBuffer(StreamEncoder.java:104)
- locked <0x00000000d4407840> (a java.io.OutputStreamWriter)
at java.io.OutputStreamWriter.flushBuffer(OutputStreamWriter.java:185)
at java.io.PrintStream.newLine(PrintStream.java:546)
- eliminated <0x00000000d4407748> (a java.io.PrintStream)
at java.io.PrintStream.println(PrintStream.java:807)
- locked <0x00000000d4407748> (a java.io.PrintStream)
at org.example.App$1.run(App.java:17)
at java.lang.Thread.run(Thread.java:745)
定位可疑代码:at org.example.App$1.run(App.java:17) 发现代码在死循环
Thread thread= new Thread(group,new Runnable() {
@Override
public void run() {
while (true){
System.out.println( "runing!" );
}
}
});
5) jmap -dump:live,format=b,file=7181.dump 7181
jmap命令是一个可以输出所有内存中对象的工具
基本参数:
-dump:[live,]format=b,file=<filename> 使用hprof二进制形式,输出jvm的heap内容到文件=. live子选项是可选的,假如指定live选项,那么只输出活的对象到文件.
-finalizerinfo 打印正等候回收的对象的信息.
-heap 打印heap的概要信息,GC使用的算法,heap的配置及wise heap的使用情况.
-histo[:live] 打印每个class的实例数目,内存占用,类全名信息. VM的内部类名字开头会加上前缀”*”. 如果live子参数加上后,只统计活的对象数量.
-permstat 打印classload和jvm heap长久层的信息. 包含每个classloader的名字,活泼性,地址,父classloader和加载的class数量. 另外,内部String的数量和占用内存数也会打印出来.
-F 强迫.在pid没有相应的时候使用-dump或者-histo参数. 在这个模式下,live子参数无效.
-h | -help 打印辅助信息
-J 传递参数给jmap启动的jvm.
pid 需要被打印配相信息的java进程id
[root@192 test]# jmap -dump:live,format=b,file=7181.dump 7181
Dumping heap to /opt/test/7181.dump ...
Heap dump file created