jstack分析cpu占用100%

本文介绍如何使用jstack工具来分析Java应用程序中导致CPU占用过高的问题,并通过一个实例展示了如何获取和解读堆栈信息。
[b]jstack用于打印出给定的java进程ID或core file或远程调试服务的Java堆栈信息[/b],经常用来分析java应用程序CPU占用过高的问题。

假定有以下代码:

public class App
{
public static void main(String[] args)
{
Thread td = new Thread()
{

@Override
public void run()
{
while (true) {
;
}
}
};

td.start();

while (true) {
;
}
}

}

执行时CPU占用 100%

在命令行cmd执行:
jps 得到进程的PID号 10284

C:\JavaDev\jdk1.6.0_02\bin>jps
CryptQueryObject failed with 80092009
12240 Jps
5836 Program
10284 App

C:\JavaDev\jdk1.6.0_02\bin>


cmd执行 jstack -l 10284 > res.txt
得到堆截栈信息

2013-03-08 17:30:04
Full thread dump Java HotSpot(TM) Client VM (1.6.0_02-b06 mixed mode):

"Thread-0" prio=6 tid=0x0b593c00 nid=0x3244 runnable [0x0b7af000..0x0b7afa14]
java.lang.Thread.State: RUNNABLE
at App$1.run(App.java:11)

Locked ownable synchronizers:
- None

"Low Memory Detector" daemon prio=6 tid=0x0afbc000 nid=0x3300 runnable [0x00000000..0x00000000]
java.lang.Thread.State: RUNNABLE

Locked ownable synchronizers:
- None

"CompilerThread0" daemon prio=10 tid=0x0afbb000 nid=0x37e8 waiting on condition [0x00000000..0x0b4bf79c]
java.lang.Thread.State: RUNNABLE

Locked ownable synchronizers:
- None

"JDWP Command Reader" daemon prio=6 tid=0x0afad000 nid=0x26c4 runnable [0x00000000..0x00000000]
java.lang.Thread.State: RUNNABLE

Locked ownable synchronizers:
- None

"JDWP Event Helper Thread" daemon prio=6 tid=0x0afac000 nid=0x3130 runnable [0x00000000..0x00000000]
java.lang.Thread.State: RUNNABLE

Locked ownable synchronizers:
- None

"JDWP Transport Listener: dt_socket" daemon prio=6 tid=0x0afaa000 nid=0x31b8 runnable [0x00000000..0x0b3cfae0]
java.lang.Thread.State: RUNNABLE

Locked ownable synchronizers:
- None

"Attach Listener" daemon prio=10 tid=0x0af99400 nid=0x2af8 waiting on condition [0x00000000..0x00000000]
java.lang.Thread.State: RUNNABLE

Locked ownable synchronizers:
- None

"Signal Dispatcher" daemon prio=10 tid=0x0af9f800 nid=0x2f58 runnable [0x00000000..0x00000000]
java.lang.Thread.State: RUNNABLE

Locked ownable synchronizers:
- None

"Finalizer" daemon prio=8 tid=0x0af88400 nid=0x29a4 in Object.wait() [0x0b0ff000..0x0b0ffa94]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x02e70b48> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:116)
- locked <0x02e70b48> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:132)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159)

Locked ownable synchronizers:
- None

"Reference Handler" daemon prio=10 tid=0x0af84000 nid=0x3264 in Object.wait() [0x0b0af000..0x0b0afb14]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x02e70a48> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:485)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:116)
- locked <0x02e70a48> (a java.lang.ref.Reference$Lock)

Locked ownable synchronizers:
- None

"main" prio=6 tid=0x00bc7400 nid=0x3444 runnable [0x00dbf000..0x00dbfe50]
java.lang.Thread.State: RUNNABLE
at App.main(App.java:19)

Locked ownable synchronizers:
- None

"VM Thread" prio=10 tid=0x0af81000 nid=0x36b0 runnable

"VM Periodic Task Thread" prio=10 tid=0x0afbd800 nid=0x3278 waiting on condition

JNI global references: 992



结果给出了关键信息:
"Thread-0" prio=6 tid=0x0b593c00 nid=0x3244 runnable [0x0b7af000..0x0b7afa14]
java.lang.Thread.State: RUNNABLE
at App$1.run(App.java:11)

Locked ownable synchronizers:
- None


main" prio=6 tid=0x00bc7400 nid=0x3444 runnable [0x00dbf000..0x00dbfe50]
java.lang.Thread.State: RUNNABLE
at App.main(App.java:19)

Locked ownable synchronizers:
- None


[b]代码 11行和19行发生死锁了。[/b]
分析CPU占用过高,jstack这个工具还是挺好用的。
### 系统中断与CPU占用100%的解决方案 #### 分析问题根源 当出现瞬间的网络流量突发时,会触发大量网卡中断,这可能导致系统调用数量激增,进而耗尽CPU资源[^1]。在多核CPU环境下,如果网卡中断未能均匀分配给各个CPU核心,部分核心可能因过载而失效。 针对Java服务中的CPU 100%问题,通常涉及以下几个方面: - **死循环**:程序逻辑错误导致无限循环执行。 - **递归无终止条件**:函数递归调用缺乏必要的退出机制。 - **垃圾回收压力大**:内存管理不当引起频繁的Full GC事件[^3]。 #### 定位具体原因 为了有效解决问题,需先识别哪个进程占用了过多的CPU时间。通过操作系统命令可以获取当前运行进程中消耗最多CPU资源的那个实例。对于Linux环境而言,`top` 或 `ps aux | sort -rk3,3` 命令能够帮助完成此任务;而在Windows平台上则可利用任务管理器来查看相应信息[^2]。 一旦确定了目标进程ID (PID),下一步就是找出该进程中哪些线程正在过度使用处理器周期。借助于JDK内置诊断工具集——特别是`jstack`命令行实用程序,可以获得指定Java应用程序内部活跃线程的状态快照以及它们各自的堆栈跟踪记录。这些数据有助于进一步缩小范围至具体的代码片段或方法调用链路。 ```bash # 获取最耗费CPUJava进程ID pid=$(jcmd | grep java | awk '{print $1}') # 使用 jstack 输出指定 PID 的 Java 应用程序的线程转储文件 sudo jstack -l ${pid} > thread_dump.txt ``` #### 实施优化措施 根据上述分析结果采取针对性行动: - 如果是因为业务逻辑缺陷造成的持续性计算活动,则应修正算法实现方式; - 对于存在潜在风险的操作(如I/O密集型任务),考虑引入异步处理模型减少阻塞等待期间不必要的开销; - 配置合理的GC参数组合以平衡性能表现和吞吐量需求,避免长时间停顿现象发生; - 调整网卡中断亲和力配置,确保其能够在多个物理内核间合理分发负载,防止个别单元超负荷运转引发连锁反应。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值