http://blog.csdn.net/chenhaotong/article/details/51991786
1. top命令查看CPU和記憶體佔用率
top斷行符號,然後按1
發現進程PID 35163 CPU和記憶體佔用率都很高
top - 06:13:47 up 5:31, 1 user, load average: 2.11, 2.07, 2.06
Tasks: 189 total, 1 running, 188 sleeping, 0 stopped, 0 zombie
Cpu0 : 22.3%us, 0.7%sy, 0.0%ni, 76.4%id, 0.3%wa, 0.3%hi, 0.0%si, 0.0%st
Cpu1 :100.0%us, 0.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu2 : 8.0%us, 0.3%sy, 0.0%ni, 91.7%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu3 : 70.4%us, 1.7%sy, 0.0%ni, 25.6%id, 2.3%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 1012292k total, 943076k used, 69216k free, 9372k buffers
Swap: 1675260k total, 375204k used, 1300056k free, 34024k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
35163 user111 20 0 3823m 360m 6828 S 199.5 36.5 147:41.46 java
另外,top下,按H可以在進程PID和線程TID之間切換
2. 查看PID對應的進程
[user111@kms210 lms]$ ps -ef|grep 35163
user111 35163 1 99 04:59 pts/0 02:28:06 /usr/local/jdk1.8.0_60/bin/java -Djava.util.logging.config.file=/usr/local/lms/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.awt.headless=true -Djava.endorsed.dirs=/usr/local/lms/endorsed -classpath /usr/local/lms/bin/bootstrap.jar:/usr/local/lms/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/lms -Dcatalina.home=/usr/local/lms -Djava.io.tmpdir=/usr/local/lms/temp org.apache.catalina.startup.Bootstrap start
user111 44605 23049 0 06:14 pts/0 00:00:00 grep 35163
3. 查看線程35163中佔用CPU高的進程
[user111@kms210 lms]$ ps -mp 35163 -o THREAD,tid,time
USER %CPU PRI SCNT WCHAN USER SYSTEM TID TIME
user111 199 - - - - - - 02:32:04
user111 0.0 19 - futex_ - - 35163 00:00:00
user111 0.0 19 - poll_s - - 35164 00:00:01
user111 0.0 19 - futex_ - - 35165 00:00:01
user111 0.0 19 - futex_ - - 35166 00:00:00
user111 0.0 19 - futex_ - - 35167 00:00:00
user111 0.0 19 - futex_ - - 35168 00:00:00
user111 0.3 19 - futex_ - - 35169 00:00:16
user111 0.3 19 - futex_ - - 35170 00:00:16
user111 0.1 19 - futex_ - - 35171 00:00:05
user111 0.0 19 - futex_ - - 35172 00:00:00
user111 0.0 19 - futex_ - - 35173 00:00:01
user111 0.0 19 - futex_ - - 35174 00:00:00
user111 0.0 19 - futex_ - - 35178 00:00:00
user111 0.0 19 - ep_pol - - 35181 00:00:00
user111 0.0 19 - ep_pol - - 35182 00:00:00
user111 0.0 19 - ep_pol - - 35183 00:00:00
user111 99.6 19 - - - - 35204 01:15:33
user111 0.0 19 - futex_ - - 35222 00:00:00
user111 99.6 19 - - - - 35226 01:15:27
user111 0.0 19 - futex_ - - 35230 00:00:00
線程TID轉16進位
[user111@kms210 lms]$ printf "%x\n" 35204
8984
4.查看線程棧資訊
[user111@kms210 lms]$ jstack 35163 | grep 8984 -A 30
"Thread-6" #18 daemon prio=5 os_prio=0 tid=0x00007fb0d8fd1800 nid=0x8984 runnable [0x00007fb11cc8e000]
java.lang.Thread.State: RUNNABLE
at com.qsd.sssm.thread.LmsThread.run(LmsThread.java:68)
"NioBlockingSelector.BlockPoller-3" #15 daemon prio=5 os_prio=0 tid=0x00007fb130531800 nid=0x896f runnable [0x00007fb11dfb2000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:79)
at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
- locked <0x00000000f62278e8> (a sun.nio.ch.Util$2)
- locked <0x00000000f62278f8> (a java.util.Collections$UnmodifiableSet)
- locked <0x00000000f62278a0> (a sun.nio.ch.EPollSelectorImpl)
at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
at org.apache.tomcat.util.net.NioBlockingSelector$BlockPoller.run(NioBlockingSelector.java:342)
"NioBlockingSelector.BlockPoller-2" #14 daemon prio=5 os_prio=0 tid=0x00007fb130517000 nid=0x896e runnable [0x00007fb11e0b3000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:79)
at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
- locked <0x00000000f6227b20> (a sun.nio.ch.Util$2)
- locked <0x00000000f6227b30> (a java.util.Collections$UnmodifiableSet)
- locked <0x00000000f6227ad8> (a sun.nio.ch.EPollSelectorImpl)
at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
at org.apache.tomcat.util.net.NioBlockingSelector$BlockPoller.run(NioBlockingSelector.java:342)
"NioBlockingSelector.BlockPoller-1" #13 daemon prio=5 os_prio=0 tid=0x00007fb130474800 nid=0x896d runnable [0x00007fb11e3cd000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
[user111@kms210 lms]$
找到出現問題的代碼,並分析具體函數中是否有可能出現死迴圈的程式碼片段。
通常問題出現在while, for之類的迴圈程式碼片段。
5. 查看檔案LmsThread.java:68行
Debug一下,發現死迴圈
while (true) {
if(CMD.remoteIp.equals("")) {// 第58行,if成立,死迴圈
continue;
}
6. 另外,只替換.war檔案可能存在的問題
修改只替換.war檔案,可能會發現線程佔用率還是很高,線程棧資訊仍然顯示以前的行號的話,可以試試完整的刪除專案檔夾,重新部署整個項目
不過我們可以轉個彎,試試這樣做:
1 先用ps + grep找出該死的進程pid,比如 30420
2 top -H -p 30420,所有該進程的線程都列出來了。看看哪個線程pid佔用最多,然後將這個pid轉換為16進位,如 44bf,注意要小寫
3 jstack 30420 | less,然後尋找 nid=0x44bf,哦,找到了 (如果找不到對應的nid,可以去掉| less重新執行以下jstack命令) p.s 嚴重提示:jstack操作有風險,使用虛謹慎,俺不止一次執行jstack操作導致jvm退出,不知為啥,rp啊rp。。。本來使用JMX會安全一些的,但是翻遍ThreadInfo的doc,沒有找到有關的方法