
问题描述
系统管理员或用户已经注意到JAVA进程消耗了大量CPU资源,
我想知道哪个方面消耗了大量的CPU资源,以及导致这种现象的原因.
故障排除
请注意,并非以下所有任务都需要完成. 仅执行一些任务就可以解决一些问题.
为什么会发生此问题?
此问题的原因很多: JAVA创建的线程java程序占用cpu过高,不良的编码习惯或第三方软件.
不幸的是,有时很难证明发生此问题的位置.
此模式试图通过使用特定的操作命令并收集数据来帮助解决此问题.
收集高CPU使用率数据
有关收集CPU使用率较高的数据的具体操作信息,请根据您的操作系统执行以下步骤.
重要说明:
这些操作系统的所有信息均基于Sun JVM.
JRockit当前无法通过操作系统命令(prstat,top,pslist等)将指示CPU使用情况的操作系统命令的PID映射到线程转储中的正确线程. 可以从Jrockit的70SP4RP2和81SP2RP1开始实施此映射.
例如,在Linux中,Thread Dump在将来的版本中将采用以下形式(PID显示在Thread Dump中):
================================================ ==== ====================
“ ExecuteThread: '20'表示队列: 'default'” ID: 0x00000e80 prio: 5 ACTIVE,DAEMON,GCABLE
线程: 0x469b0af0 lastj: 0xac0f19c
pt_thr: 237596 pid: 23166
在COM.jrockit.vm.Classes.defineClass0(本机方法)上@ 0x8b4b798
在COM.jrockit.vm.Classes.defineClass(未知来源)@ 0x8b4b8b1
在java.lang.ClassLoader.defineClass(未知来源)@ 0x8b4b46f
================================================ ==== ====================
在上面的示例中,PID为23166,您可以将PID与Linux或它所在的任何系统的顶部输出(或在操作系统上需要使用的任何特定命令)直接关联.
转换为十六进制数字
备注: 为了帮助您计算此模式下讨论的十六进制值,可以在shell脚本中使用以下行将十进制数转换为十六进制数.
如果使用Unix操作系统,则转换将非常方便.
dec2hex.sh:
printf“ dec-> hex: %d =%x \ n” $ {1} $ {1}
用法:
$ sh dec2hex.sh 755
dec->十六进制: 755 = 2f3
JAVA线程转储方法: (杀死-3)
分析问题时,您需要使用kill -3 PID来生成javacore和heapdump文件
但是有时仅生成javacore文件,但不生成heapdmp文件.
由于启动此JAVA时,未在环境变量中设置相应的参数:
export JAVA_DUMP_OPTS =“ ONANYSIGNAL(JAVADUMP [5],HEAPDUMP [5])”
或

export JAVA_DUMP_OPTS =“ ONDUMP(JAVADUMP [15],HEAPDUMP [5]),ONOUTOFMEMORY(JAVADUMP [15]],HEAPDUMP [5])”
如果它是一个IBM WebSphere Application Server实例,则还可以使用export IBM_HEAPDUMP = true
IBM_HEAPDUMPDIR参数可以设置WebSphere Application Server生成的堆转储的位置
有关如何设置此参数的详细信息,请参阅:
(对于JAVA 1.4.2)
(对于Java 5)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>> >>>>>>>>
LINUX
>>>>>>>>>>>>>>>>>>>>
1. 获取顶部输出,并找到与先前启动当前使用CPU的WLS的用户ID关联的PID.
2. 使用kill -3
3. 将步骤1中的PID编号转换为十六进制值.
(Linux JVM将Java线程实现为本地线程,这使每个线程成为一个独立的Linux进程. )
4. 在“线程转储”中,搜索其nid值等于上一步中获得的十六进制值的线程.
这将揭示导致CPU使用率高的问题的线程.
以下是Linux系统中上述过程的示例:
1. 获取最上面的输出,并找到与先前启动当前使用CPU的WLS的用户ID关联的PID.
2. 将数字转换为十六进制值.
请参见下面的顶部输出示例(这只是一个代码段,因为将为单个WLS进程启动更多线程).
在Linux中,每个线程都映射到与其他Unix形式不同的进程(每个线程都有自己的PID)
================================================ ==== ====================
PID用户个人大小RSS共享STAT%CPU%MEM时间命令
...........
22962 usera 9 0 86616 84M 26780 S 0.0 4.2 0:00 java
...........
================================================ ==== ====================
注意: ps和top仅显示主(初始)线程. 要查看所有线程,请使用ps -m命令或在顶部组合键中输入[Shift]-[H].
如果PID为22962,则十六进制值为: 0x59B2
3. 使用此十六进制值并程转储中查找哪个nid等于该值java程序占用cpu过高,以便从线程转储中获取正确的线程.
例如,如果ExecuteThread 0存在问题,则0x59B2将对应于该线程:
================================================ ==== ===========================
“ ExecuteThread: '0'表示队列: 'default'”守护程序prio = 1 tid = 0x83da550 nid = 0x59b2在监视器[0x56138000..0x56138870]中等待
在java.lang.Object.wait(本机方法)
在java.lang.Object.wait(Object.java:415)
在weblogic.kernel.ExecuteThread.waitForRequest(ExecuteThread.java:146)
在weblogic.kernel.ExecuteThread.run(ExecuteThread.java:172)
================================================ ==== =====================
4. 然后,您可以检查线程以确定它正在执行什么任务以及是否存在问题.

在上面的示例中,由于此时线程正在占用CPU的0%,因此仅显示执行此操作的进程.
理想情况下,所有三个步骤都应该快速且连续地完成,以尽快捕获数据.
这可以通过类似于以下内容的简单shell脚本来完成.
================================================ ==== =====================
#
#接受一个参数(WLS进程的PID)并循环3次.
#这会将prstat信息附加到名为dump_high_cpu.txt的文件中.
#线程转储信息将在重定向stdout的文件中或在屏幕上显示.
#
用于1 2 3中的循环数
做
top -b -n1 >> dump_high_cpu.txt
杀死-3 $ 1
echo“ cpu快照和线程转储完成. #” $ loopnum
睡觉1
回声“睡着了. ”
完成
================================================ ==== ============================
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>> >>>>>>>>>>>>>>>>>>
SOLARIS
>>>>>>>>>>>>>>>>>>>>
1. 在Java进程中运行prstat命令. 重复几次此操作,以便可以看到图案. 例如: prstat -L -p
2. 在Java进程中运行pstack命令,以获取从轻量级进程(LWP)到PID(进程ID)的映射.
示例: pstack 9499并将输出重定向到文件.
如果您在Solaris中使用常规线程库(即LD_LIBRARY_PATH中没有/ usr / lib / lwp),
LWP不会直接映射到操作系统线程,因此您必须从进程中执行pstack(因此请检查是否正在使用备用线程库).
3. 一段时间后,请在服务器上执行几个线程转储,以确保执行正确的线程.
您可以通过在Java进程中执行kill -3
4. 将LWP ID映射到Java线程ID.
例如,如果上述LWP为“ 8”,则可以将其映射到Java线程“ 76”. 然后将76转换为十六进制值0x4c.
5. 检查线程转储,找到与“ nid = <标识符/值>”匹配的线程.
在此示例中,您找到一个匹配“ nid = 0x4c”的线程,而该线程是消耗CPU资源的线程.
以下是Solaris系统中上述过程的示例:
1. 在Java进程中运行prstat命令.
================================================ ==== =====================
$ prstat -L -p 9499 1 1
PID用户名大小RSS状态优先时间CPU进程/ LWPID
9499 usera 153M 100M睡眠58 0 0: 00.22 0.6%Java / 8

9499 usera 153M 100M睡眠58 0 0: 00.10 0.2%java / 10
9499 usera 153M 100M睡眠58 0 0: 00.11 0.1%Java / 9
9499 usera 153M 100M睡眠58 0 0: 00.03 0.0%java / 5
9499 usera 153M 100M睡眠58 0 0: 01.01 0.0%java / 1
9499 usera 153M 100M睡眠58 0 0: 00.00 0.0%java / 12
9499 usera 153M 100M睡眠58 0 0: 00.00 0.0%java / 11
9499 usera 153M 100M睡眠58 0 0: 00.00 0.0%java / 14
9499 usera 153M 100M睡眠58 0 0: 00.00 0.0%java / 13
9499 usera 153M 100M睡眠59 0 0: 00.07 0.0%java / 7
9499 usera 153M 100M睡眠59 0 0: 00.00 0.0%java / 6
9499 usera 153M 100M睡眠59 0 0: 00.00 0.0%java / 4
9499 usera 153M 100M睡眠58 0 0: 00.11 0.0%java / 3
9499 usera 153M 100M睡眠58 0 0: 00.00 0.0%java / 2
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/ruanjian/article-207043-1.html
一年后就没阿里了