今天一个电话面试问了这个问题。回来查了下答案,自己也顺带操作一遍,做个记录。之前只知道jstack工具可以查看线程状态这些。比如死锁这些,主要是之前不知道top -H -p pid这个命令的使用,这命令可以看到进程下面线程信息,拿到线程ID,然后再结合jstack命令使用就可以解决这个问题了。下面记录一下具体的操作步骤:
1.打个jar包丢到机器上运行
1 package com.nijunyang.test; 2 3 4 5 public class TestApplication { 6 7 public static void main(String[] args) { 8 for (int i = 0; i < 50; i++) { 9 new Thread(()->test()).start(); 10 } 11 12 } 13 14 public static void test() { 15 while (true) { 16 int a = 1 + 6; 17 System.out.println(a); 18 } 19 } 20 }
使用这个maven插件 打包jar
1 <plugin> 2 <groupId>org.apache.maven.plugins</groupId> 3 <artifactId>maven-assembly-plugin</artifactId> 4 <configuration> 5 <archive> 6 <manifest> 7 <mainClass>com.nijunyang.test.TestApplication</mainClass> 8 </manifest> 9 </archive> 10 <descriptorRefs> 11 <descriptorRef>jar-with-dependencies</descriptorRef> 12 </descriptorRefs> 13 </configuration> 14 <executions> 15 <execution> 16 <id>make-assembly</id> 17 <phase>package</phase> 18 <goals> 19 <goal>single</goal> 20 </goals> 21 </execution> 22 </executions> 23 </plugin>
2. java -jar test-0.0.1-SNAPSHOT-jar-with-dependencies.jar 运行程序
一直在输出
3.top |grep java 或者 jps指令找到java进程的pid(6167)
4. top -H -p pid 以线程的形式查看该进程 top -H -p 6167
因为我们程序是起了50个线程 所以这里就会展示这个进程中的所有线程呢
5.前面的线程ID是10进制的,,需要转换成16进制,,因为等下在jstack命令取出来的线程ID是16进制的:这里就随便选一个线程ID 去转换了,真实环境肯定是选择CPU占用率最高的那个线程,echo "obase=16;6219" | bc
6.jstack 6167 >threadInfo.txt 信息输出到文件 然后查看。也可以直接在命令里面查看
7.文件中查找184b的线程ID信息,就可以找到是哪个线程导致的内存占用过高,同时也能看到具体的代码位置