Linux下javajava 进程 占用内存CPU占用率高如何定位问题

使用场景:
遇到Linux下java应用cpu占用很高的时候,我们很想知道此时的应用到底在做什么导致资源的消耗。
方便我们进一步定位和优化~
1、查询cpu耗用top5的进程(你也可以top10)
[root@FATD ~]#&ps H -eo user,pid,ppid,tid,time,%cpu,cmd --sort=-%cpu | head -5
可以看到上面TID为322的cpu占用是第一的。
2、将线程ID转换为16进制格式
[root@FATD ~]# printf "%x\n"&322
printf "%x\n"&tid
3、打印线程ID堆栈信息
[root@FATD ~]#&jstack 43 |grep 0x142 -A 30
jstack&pid&|grep 0xtid&-A 30
有堆栈信息后,就可以明确的知道,此时此刻就是这个东东在消耗cpu资源
**********************************
BTW:此方法验证和使用JMX监控方法的结果一致
(说明:示例服务本身没什么问题)
原文链接地址:https://zhuanlan.zhihu.com/p/
阅读(...) 评论()linux下查找java进程占用CPU过高原因1. 查找进程top查看进程占用资源情况明显看出java的两个进程2占用过高cpu. 2.查找线程使用top -H -p &pid&查看线程占用情况 3.查找java的堆栈信息将线程id转换成十六进制#printf %x 15664#3d30 然后再使用jstack查询线程的堆栈信息语法:jstack &pid& | grep -a 线程id(十六进制) jstack &pid& | grep -a 3d30 这样就找出了有问题的代码了。 剩下的就是分析原因和修改代码了。
声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至: 进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。问题描述
系统管理员或用户注意到 JAVA 进程消耗大量的 CPU 资源,
并想要了解是哪个方面消耗了大量 CPU 资源,以及导致出现这种现象的原因。
故障排除
请注意,并非下面所有任务都需要完成。有些问题仅通过执行几项任务就可以解决。
为什么发生此问题?
发生此问题有许多原因:JAVA创建的线程、不良编码习惯或第三方软件。
遗憾的是,证明在什么地方发生此问题有时候非常困难。
本模式尝试通过利用特定操作命令和收集数据来帮助排除此问题。
收集高 CPU 占用率的数据
对于有关收集高 CPU 占用率的数据的特定操作信息,请根据您的操作系统执行以下步骤。
重要说明:
这些操作系统的所有信息都基于 Sun JVM。
目前在 JRockit 中还没有办法将 PID 从说明 CPU 占用率的操作系统命令(prstat、top、pslist 等等) 映射到 Thread Dump 中的正确线程。 从 Jrockit 的 70SP4RP2 和 81SP2RP1 以后的版本起,就可实现此映射。
例如,在 Linux 中,Thread Dump 在以后的版本中将采用如下形式(PID 显示在 Thread Dump 中):
=====================================================================
"ExecuteThread: '20' for queue: 'default'" id: 0x00000e80 prio: 5 ACTIVE, DAEMON, GCABLE
&&& thread: 0x469b0af0 lastj: 0xac0f19c
&&& pt_thr: 237596 pid: 23166
&&& at COM.jrockit.vm.Classes.defineClass0(Native Method)@0x8b4b798
&&& at COM.jrockit.vm.Classes.defineClass(Unknown Source)@0x8b4b8b1
&&& at java.lang.ClassLoader.defineClass(Unknown Source)@0x8b4b46f
=====================================================================
在上例中,PID 是 23166,您可以通过 Linux 或任何所在系统上的 top(或任何您需要在操作系统上使用的特定命令)输出直接关联该 PID。
转换为十六进制号码
备注:为协助您计算在本模式中讨论的十六进制值,您可以在 Shell 脚本中使用下列行将十进制号码转换为十六进制号码。
如果您使用 Unix 操作系统,那么转换会很方便。
dec2hex.sh:
&&& printf "dec -& hex: %d = %x \n" ${1} ${1}
用法:
&&& $ sh dec2hex.sh 755
&&& dec -& hex: 755 = 2f3
JAVA Thread Dump 方法:(kill -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 instance,还可以使用 export IBM_HEAPDUMP=true
而 IBM_HEAPDUMPDIR 这个参数可以设置WebSphere Application Server生成的heapdump的位置
具体这个如何设置这个参数可以参考:
http://publib.boulder.ibm.com/infocenter/javasdk/v1r4m2/index.jsp (for JAVA 1.4.2)
http://publib.boulder.ibm.com/infocenter/javasdk/v5r0/index.jsp (for JAVA 5)
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&& LINUX
&&&&&&&&&&&&&&&&
1.获得最顶端输出并查找与之前启动了现占用 CPU 的 WLS 的那个用户 ID 相关联的 PID。
2.通过 kill -3 &PID& 对 WebLogic Server 进行若干 Thread Dump
3.将步骤 1 中的 PID 号转换为一个十六进制值。
&&& (用于 Linux 的 JVM 将 Java 线程作为本地线程实现,这使每个线程成为一个独立的 Linux 进程。)
&&
4.在 Thread Dump 中搜索 nid 的值等于上一步骤中所得到的十六进制值的线程。
&&&& 这将为您揭示造成高 CPU 占用率问题的线程。
&
下面是 Linux 系统中上述进程的一个示例:
1.获得 top输出并查找与之前启动了现占用 CPU 的 WLS 的那个用户 ID 相关联的 PID。
2.将该号转换为一个十六进制值。
&&& 请参阅下面的 top 输出示例(这只是一个代码片断,因为对于单个 WLS 进程将启动更多的线程)。
&&& 在 Linux 中,每个线程映射到一个不同于其它 Unix 形式的进程中(每个线程都有自己的 PID)
&&&&
&&& =====================================================================
&&& PID&&&&& USER&&&& PRI&&&&& NI&&& SIZE&&& RSS&&& SHARE&&& STAT&&&& %CPU&&& %MEM&&& TIME&&& COMMAND
&&& ...........
&&& 22962&&& usera&&&&& 9&&&&&& 0&& 86616&&& 84M&&& 26780&&&&&& S&&&&& 0.0&&&& 4.2&&& 0:00&&&&&& java
&&& ...........
&&& =====================================================================
&&& 备注:ps 和 top 只显示主(初始)线程。要查看所有线程,使用 ps -m 命令或在 top 中键入[Shift] -[H] 组合键。
&&& 如果 PID 为 22962,则十六进制值将是:0x59B2
3.使用此十六进制值并在 Thread Dump 中查找哪个 nid 等于该值,以便从 Thread Dump 中获取正确的线程。
&&& 例如,如果 ExecuteThread 0 出现问题,则 0x59B2 将对应于该线程:
&&& ===========================================================================
&&& "ExecuteThread: '0' for queue: 'default'" daemon prio=1 tid=0x83da550 nid=0x59b2 waiting on monitor [0xx]
&&&&&&& at java.lang.Object.wait(Native Method)
&&&&&&& at java.lang.Object.wait(Object.java:415)
&&&&&&& at weblogic.kernel.ExecuteThread.waitForRequest(ExecuteThread.java:146)
&&&&&&& at weblogic.kernel.ExecuteThread.run(ExecuteThread.java:172)
&&& ======================================================================
4.然后,您可以检查该线程以确定它正在执行的任务以及是否出现问题。
在上述示例中,由于该线程此时占用 0% 的 CPU,所以只显示执行此操作的进程。
理想状态下,应当迅速并且连续完成全部三个步骤,以便尽可能及时地捕捉数据。
这可以通过类似下面的一个简单的 shell 脚本来完成。
======================================================================
#
# Takes an argument (PID of the WLS process) and loops three times.
# This will append the prstat information to a file called dump_high_cpu.txt.
# The thread dump information will either be in file where stdout was redirected or printed on the screen.
#
for loopnum in 1 2 3
do
&&&& top -b -n1&& dump_high_cpu.txt
&&&& kill -3 $1
&&&& echo "cpu snapshot and thread dump done. #" $loopnum
&&&& sleep 1
&&&& echo "Done sleeping."
done
============================================================================
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&& SOLARIS
&&&&&&&&&&&&&&&&
1.在 Java 进程中运行 prstat命令。重复几次这个操作,以便您能够看到一种模式。例如:prstat -L -p &PID& 1 1
2.在 Java 进程中运行 pstack命令以获得从轻量型进程 (LWP) 到 PID(进程 ID)的映射。
&&& 示例:pstack 9499 并将输出结果重定向到一个文件。
&&& 如果您使用 Solaris 中的常规线程库(即,在 LD_LIBRARY_PATH 中没有 /usr/lib/lwp),
&&& LWP 就不会直接映射到操作系统线程,因此您必须从进程中执行 pstack(所以检查看您是否正在使用替代线程库)。
3.经过一段时间后对服务器进行若干 Thread Dump,确保您执行正确的线程。
&&& 您可以通过在 Java 进程中执行 kill -3 &PID&来达到此目的。
4.将 LWP ID 映射到 Java 线程 ID。
&&& 例如,如果上述的 LWP 为“8”,它可以映射到 Java 线程“76”。然后将 76 换算为十六进制值 0x4c。
5.检查 Thread Dump,找到匹配“nid= &上述标识符/值&”的线程。
&&& 在本示例中,您找到匹配“nid=0x4c”的线程,而该线程就是正在消耗 CPU 资源的那个线程。
下面是 Solaris 系统中上述进程的一个示例:
1. 在 Java 进程中运行 prstat 命令。
======================================================================
$ prstat -L -p
PID USERNAME&& SIZE RSS STATE PRI NICE&& TIME&&& CPU PROCESS/LWPID
9499 usera&&&&& 153M 100M sleep&& 58&&& 0&& 0:00.22 0.6% java/8
9499 usera&&&&& 153M 100M sleep&& 58&&& 0&& 0:00.10 0.2% java/10
9499 usera&&&&& 153M 100M sleep&& 58&&& 0&& 0:00.11 0.1% java/9
9499 usera&&&&& 153M 100M sleep&& 58&&& 0&& 0:00.03 0.0% java/5
9499 usera&&&&& 153M 100M sleep&& 58&&& 0&& 0:01.01 0.0% java/1
9499 usera&&&&& 153M 100M sleep&& 58&&& 0&& 0:00.00 0.0% java/12
9499 usera&&&&& 153M 100M sleep&& 58&&& 0&& 0:00.00 0.0% java/11
9499 usera&&&&& 153M 100M sleep&& 58&&& 0&& 0:00.00 0.0% java/14
9499 usera&&&&& 153M 100M sleep&& 58&&& 0&& 0:00.00 0.0% java/13
9499 usera&&&&& 153M 100M sleep&& 59&&& 0&& 0:00.07 0.0% java/7
9499 usera&&&&& 153M 100M sleep&& 59&&& 0&& 0:00.00 0.0% java/6
9499 usera&&&&& 153M 100M sleep&& 59&&& 0&& 0:00.00 0.0% java/4
9499 usera&&&&& 153M 100M sleep&& 58&&& 0&& 0:00.11 0.0% java/3
9499 usera&&&&& 153M 100M sleep&& 58&&& 0&& 0:00.00 0.0% java/2
====================================================================
2.运行 pstack 命令。
&&
&&& 示例:pstack 9499 并将输出结果重定向到一个文件。
&&& 如果您使用 Solaris 中的常规线程库(即,在 LD_LIBRARY_PATH 中没有 /usr/lib/lwp),
&&& LWP 就不会直接映射到操作系统线程,因此您必须从进程中执行 pstack(所以检查看您是否正在使用替代线程库)。
&&& 上述示例显示“java/8”进程在 prstat 的顶端。
3.为“lwp# 8”检验 pstack输出结果。
&&& 您会发现“lwp# 8”从 pstack 输出结果映射到“thread# 76”,如下所示。
&&& =================================================================
&&& ----------------- lwp# 8 / thread# 76 --------------------
&&& ff29d190 poll&&&& (e2e81548, 0, bb8)
&&& ff24d154 select&& (0, 0, 0, e2e81548, ff2bf1b4, e2e81548) + 348
&&& ff36b134 select&& (0, bb8, 7fffffff, fe4c8000, 0, bb8) + 34
&&& fe0f62e4 __1cCosFsleep6FpnGThread_xl_i_ (0, bb8, fe4c, 1e2fd8) + 234
&&& fe23f050 JVM_Sleep (2, 0, bb8, fe4de978, fe4cfd8) + 22c
&&& 0008f7ac ???????? (e2e818d4, bb8, 1e2fd8, 984a4, 0, 109a0)
&&&
???????? (e2e8194c, 1, fe4d6a80, 98564, 8, e2e81868)
&&& fe5324e8 __1cMStubRoutinesG_code1_ (e2e819d8, e2e81c10, a, f6cb5000, 4, e2e818f0) + 3ec
&&& fe0cbe94 __1cJJavaCallsLcall_helper6FpnJJavaValue_pnMmethodHandle_pnRJavaCallArguments_pnGThread__v_ (e2e81c08,fe4c8000, e2e81b54, 1e2fd8, 8e764, e2e81c10) +308
&&& fe1f6dbc __1cJJavaCallsMcall_virtual6FpnJJavaValue_nLKlassHandle_nMsymbolHandlee81c08, e2e81b54) + 150pnGThread__v_(f6cb64b8, e2e81b40, e2e81b44, fe4c8000, e2d8) + 60e_5pnGThread__v_ (e2e81c08, e2e81c04, e2e81c00,e2e81bf4, e2e81bec, 1e2f8000, e2e81d10, 1e, e) + 120FpnKJavaThread_pnGThread__v_ (fe2fd8, fe4c
&&& 7fd70) + 3d8cKJavaThreadDrun6M_v_ (e2e02000, fe4d3e34, fe4c, 1e2fd8,
&&& fe213ec8 _start&& (fe4c8000, fe625d10, 0, 5, 1, fe401000) + 20
&&& ff36b728 _thread_start (1e2fd8, 0, 0, 0, 0, 0) + 40
&&& ======================================================================
4.通过在 Java 进程中执行以下命令对服务器进行 Thread Dump:
&&& kill -3 &PID&。
&&&
5.由于 lwp# 8 映射到 thread #76,您可以将 76 换算为十六进制值 4c。
&&& 该值映射到 JVM Thread Dump 中的 nid=0x4c:
&&&
&&& ================================================================
&&& "Thread-6" prio=5 tid=0x1e2fd8 nid=0x4c waiting on monitor [0xe2e8e819d8]
&&&&&&&&&&& at java.lang.Thread.sleep(Native Method)
&&&&&&&&&&& at weblogic.management.deploy.GenericAppPoller.run(GenericAppPoller.java:139)
&&& =======================================================================
&&& 在此示例中,占用最多 CPU 资源的线程实际上正处于休眠状态。应用程序轮询程序在开发模式启动的服务器上运行。
&&& 由于它每隔 30 秒运行一次,因此显然无法及时捕捉 Thread Dump 以了解此线程中的活动。
&&& 理想状态下,应当迅速并且连续完成全部三个步骤,以便尽可能及时地捕捉数据。这可以通过类似下面的一个简单的 shell 脚本来完成。
&&& =========================================================================
&&& #
&&& # Takes an argument (PID of the WLS process) and loops three times.
&&& # This will append the prstat information to a file called dump_high_cpu.txt.
&&& # The thread dump information will either be in file where stdout was redirected or printed on the screen.
&&& #
&&& for loopnum in 1 2 3
&&& do
&&&&&& prstat -L -p $1 1 1 && dump_high_cpu.txt
&&&&&& pstack $1 && dump_high_cpu.txt
&&&&&& kill -3 $1
&&&&&& echo "prstat, pstack, and thread dump done. #" $loopnum
&&&&&& sleep 1
&&&&&& echo "Done sleeping."
&&& done
&&& =====================================================================
6.然后,您可以检查该线程以确定它正在执行的任务以及是否出现问题。
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&& AIX
&&&&&&&&&&&&&&&&
1. 执行: ps -mp &PID& -o THREAD 以查找正在占用 CPU 的 tid。
&& 您应当查看“CP”列(表示 CPU 占用率),看其中哪些线程的此项值比较高并从中挑选一个线程。
2. 通过执行以下命令对服务器进行 Thread Dump:
&& kill -3 &PID&
3. 运行: dbx -a &PID&
4. 在 dbx 中时,运行 dbx thread命令(以列出所有线程)。
5. 查找与您通过 ps -mp &PID -o THREAD 命令获取的 TID 匹配的行。
&& 该行中的号码应当采用“$t&NUM&”格式,其中“NUM”是一个号码。
6. 在 dbx 中时,运行 dbx 命令 th info &TID&(此 TID 来自上一步骤,该步骤在 $t&NUM&后面列出号码)以获取关于该线程的信息。
7. 从第 3 步骤的输出中,在“general”下查找“pthread_t”,并记录该十六进制号码。
8. 非常重要说明:在 dbx 提示符下,您需要在完成操作时在 dbx 命令行键入“detach”,否则,如果您在连接到进程时只要一退出,dbx 将终止该进程!
9. 记下“p_thread_t”输出中的十六进制值,并在 Thread Dump 中搜索其中哪个线程的“native ID”等于该值。
&& 这将为您揭示造成高 CPU 占用率问题的线程。
文来自CSDN博客,转载请标明出处:http://blog.csdn.net/subchen/archive//5801072.aspx
chenming100_1976
浏览: 27226 次
来自: 南京
ant部署WebService的三步走.rar中的非常详细,非 ...
貌似没有源码、能否发我一份
文件解压需要密码?哥们
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'博客分类:
引用
一般linux系统内用这些命令获取系统信息:
&info name="cpuCmd" value="top -b -n 1|grep Cpu"&&/info&
&info name="memCmd" value="top -b -n 1|grep Mem"&&/info&
&info name="spaceCmd" value="df -h|sed -n '3,$p'"&&/info&&!-- 需要检查系统df命令,是否'3,$p'第三行开始是磁盘信息 --&
----------------------------------------------
获取单个进程CPU,内存的占用率
cmd脚本命令:top -b -n 1 -p $pid | sed '$d' | sed -n '$p'
上面的$pid,就是进程的PID
获取当前进程的CPU占有率
cmd:top -b -n 1 -p $pid | sed '$d' | sed -n '$p' | awk '{print $9}'
* @Title: getProcCpu
* @Description: TODO
* @author:zjz
* @create-date: 下午6:22:53
* @modify-date: 下午6:22:53
* @param @param pid
* @param @return
* @return double
public double getProcCpu(int pid){
Process process=
BufferedReader br =
if("".equals(procCpuShell))return 0;
procCpuShell = procCpuShell.replaceAll("\\$pid", pid+"");
String[] cmd = new String[]{"/bin/sh","-c",procCpuShell};
process = Runtime.getRuntime().exec(cmd);
int resultCode = process.waitFor();
LogCvt.debug("执行结果PID:"+pid+":"+resultCode);
br = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line =
while((line = br.readLine())!=null ){
Double cpu = Double.parseDouble(line);
if(cpu&100)cpu = cpu/10;//刚启动会出现CPU100多情况,则处理除于10
} catch (Exception e) {
LogCvt.error("执行获取进程CPU使用率错误",e);
if(process!=null)process.destroy();
if(br!=null)br.close();
}catch(Exception e){
LogCvt.error(e.getMessage());
return 0.0;
如果要获取单个进程使用的内存可以这样:
int mb = ;
// 可使用内存
long totalMemory = Runtime.getRuntime().totalMemory() /
// 剩余内存
long freeMemory = Runtime.getRuntime().freeMemory() /
// 最大可使用内存
long maxMemory =Runtime.getRuntime().maxMemory() /
浏览: 35455 次
来自: 广州
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'

我要回帖

更多关于 java进程占用cpu 的文章

 

随机推荐