哪个 Java 线程正在占用 CPU?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/930915/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Which Java thread is hogging the CPU?
提问by Gene Vayngrib
Let's say your Java program is taking 100% CPU. It has 50 threads. You need to find which thread is guilty. I have not found a tool that can help. Currently I use the following very time consuming routine:
假设您的 Java 程序占用了 100% 的 CPU。它有 50 个线程。你需要找出哪个线程是有罪的。我还没有找到可以提供帮助的工具。目前我使用以下非常耗时的例程:
- Run
jstack <pid>
, where pid is the process id of a Java process. The easy way to find it is to run another utility included in the JDK -jps
. It is better to redirect jstack's output to a file. - Search for "runnable" threads. Skip those that wait on a socket (for some reason they are still marked runnable).
- Repeat steps 1 and 2 a couple of times and see if you can locate a pattern.
- Run
jstack <pid>
,其中 pid 是 Java 进程的进程 ID。找到它的简单方法是运行 JDK 中包含的另一个实用程序 -jps
. 最好将 jstack 的输出重定向到一个文件。 - 搜索“可运行”线程。跳过那些在套接字上等待的(出于某种原因,它们仍然被标记为可运行)。
- 重复第 1 步和第 2 步几次,看看您是否可以找到一个模式。
Alternatively, you could attach to a Java process in Eclipse and try to suspend threads one by one, until you hit the one that hogs CPU. On a one-CPU machine, you might need to first reduce the Java process's priority to be able to move around. Even then, Eclipse often isn't able to attach to a running process due to a timeout.
或者,您可以附加到 Eclipse 中的 Java 进程并尝试一个一个挂起线程,直到遇到占用 CPU 的线程。在单 CPU 机器上,您可能需要先降低 Java 进程的优先级才能四处移动。即便如此,由于超时,Eclipse 通常无法附加到正在运行的进程。
I would have expected Sun's visualvm
tool to do this.
我本来希望 Sun 的visualvm
工具可以做到这一点。
Does anybody know of a better way?
有人知道更好的方法吗?
采纳答案by Cowan
Try looking at the Hot Thread Detector plugin for visual VM-- it uses the ThreadMXBean API to take multiple CPU consumption samples to find the most active threads. It's based on a command-line equivalent from Bruce Chapmanwhich might also be useful.
尝试查看Visual VM的Hot Thread Detector 插件——它使用 ThreadMXBean API 来获取多个 CPU 消耗样本以查找最活跃的线程。它基于Bruce Chapman 的等效命令行,这也可能有用。
回答by Paul Fisher
This is a kind of hacky way, but it seems like you could fire the application up in a debugger, and then suspend allthe threads, and go through the code and find out which one isn't blocking on a lock or an I/O call in some kind of loop. Or is this like what you've already tried?
这是一种hacky方式,但似乎您可以在调试器中启动应用程序,然后挂起所有线程,并检查代码并找出哪个没有阻塞锁或I / O 调用某种循环。或者这就像你已经尝试过的一样?
回答by Lawrence Dol
Just run up JVisualVM, connect to your app and and use the thread view. The one which remains continually active is your most likely culprit.
只需运行 JVisualVM,连接到您的应用程序并使用线程视图。保持持续活跃的那个是你最有可能的罪魁祸首。
回答by jdigital
If you're running under Windows, try Process Explorer. Bring up the properties dialog for your process, then select the Threads tab.
如果您在 Windows 下运行,请尝试Process Explorer。打开进程的属性对话框,然后选择线程选项卡。
回答by talonx
Take a thread dump. Wait for 10 seconds. Take another thread dump. Repeat one more time. Inspect the thread dumps and see which threads are stuck at the same place, or processing the same request. This is a manual way of doing it, but often useful.
进行线程转储。等待 10 秒钟。采取另一个线程转储。再重复一次。检查线程转储并查看哪些线程卡在同一位置或处理同一请求。这是一种手动方式,但通常很有用。
回答by Neil Coffey
An option you could consider is querying your threads for the answer from within application. Via the ThreadMXBeanyou can query CPU usage of threads from within your Java application and query stack traces of the offending thread(s).
您可以考虑的一个选项是从应用程序中查询您的线程以获得答案。通过ThreadMXBean,您可以从 Java 应用程序中查询线程的 CPU 使用率,并查询违规线程的堆栈跟踪。
The ThreadMXBean option allows you to build this kind of monitoring into your live application. It has negligible impact and has the distinct advantage that you can make it do exactly what you want.
ThreadMXBean 选项允许您将这种监控构建到您的实时应用程序中。它的影响可以忽略不计,并且具有明显的优势,您可以让它完全按照您的意愿行事。
回答by Peter Lawrey
If you suspect VisualVM is a good tool, try it (because it does this) Find out the threads(s) only helps you in the general direction of why it is consuming so much CPU.
如果您怀疑 VisualVM 是一个很好的工具,请尝试一下(因为它可以做到这一点) 找出线程只会帮助您了解为什么它消耗这么多 CPU 的大致方向。
However, if its that obvious I would go straight to using a profiler to find out why you are consuming so much CPU.
但是,如果它很明显,我会直接使用分析器来找出为什么消耗这么多 CPU。
回答by Mark
Have a look at the Top Threadsplugin for JConsole.
查看JConsole的Top Threads插件。
回答by MRalwasser
jvmtopcan show you the top consuming threads:
jvmtop可以显示消耗最高的线程:
TID NAME STATE CPU TOTALCPU
25 http-8080-Processor13 RUNNABLE 4.55% 1.60%
128022 RMI TCP Connection(18)-10.101. RUNNABLE 1.82% 0.02%
36578 http-8080-Processor164 RUNNABLE 0.91% 2.35%
128026 JMX server connection timeout TIMED_WAITING 0.00% 0.00%
回答by Vassilis Blazos
Identifying which Java Thread is consuming most CPU in production server.
确定生产服务器中哪个 Java 线程消耗最多的 CPU。
Most (if not all) productive systems doing anything important will use more than 1 java thread. And when something goes crazy and your cpu usage is on 100%, it is hard to identify which thread(s) is/are causing this. Or so I thought. Until someone smarter than me showed me how it can be done. And here I will show you how to do it and you too can amaze your family and friends with your geek skills.
大多数(如果不是全部)生产系统做任何重要的事情都会使用 1 个以上的 Java 线程。当某些事情变得疯狂并且您的 CPU 使用率达到 100% 时,很难确定是哪个线程导致了这种情况。或者我是这么想的。直到有人比我更聪明向我展示了如何做到这一点。在这里,我将向您展示如何做到这一点,您也可以用您的极客技能让您的家人和朋友惊叹不已。
A Test Application
测试应用程序
In order to test this, we need a test application. So I will give you one. It consists of 3 classes:
为了测试这一点,我们需要一个测试应用程序。所以我会给你一个。它由3个类组成:
- A
HeavyThread
class that does something CPU intensive (computing MD5 hashes) - A
LightThread
class that does something not-so-cpu-intensive (counting and sleeping). - A
StartThreads
class to start 1 cpu intensive and several light threads.
- 一个
HeavyThread
做一些 CPU 密集型(计算 MD5 哈希)的类 - 一个
LightThread
执行不那么 CPU 密集型(计数和睡眠)的类。 - 一个
StartThreads
类来启动 1 个 CPU 密集型和几个轻线程。
Here is code for these classes:
下面是这些类的代码:
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;
/**
* thread that does some heavy lifting
*
* @author srasul
*
*/
public class HeavyThread implements Runnable {
private long length;
public HeavyThread(long length) {
this.length = length;
new Thread(this).start();
}
@Override
public void run() {
while (true) {
String data = "";
// make some stuff up
for (int i = 0; i < length; i++) {
data += UUID.randomUUID().toString();
}
MessageDigest digest;
try {
digest = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
// hash the data
digest.update(data.getBytes());
}
}
}
import java.util.Random;
/**
* thread that does little work. just count & sleep
*
* @author srasul
*
*/
public class LightThread implements Runnable {
public LightThread() {
new Thread(this).start();
}
@Override
public void run() {
Long l = 0l;
while(true) {
l++;
try {
Thread.sleep(new Random().nextInt(10));
} catch (InterruptedException e) {
e.printStackTrace();
}
if(l == Long.MAX_VALUE) {
l = 0l;
}
}
}
}
/**
* start it all
*
* @author srasul
*
*/
public class StartThreads {
public static void main(String[] args) {
// lets start 1 heavy ...
new HeavyThread(1000);
// ... and 3 light threads
new LightThread();
new LightThread();
new LightThread();
}
}
Assuming that you have never seen this code, and all you have a PID of a runaway Java process that is running these classes and is consuming 100% CPU.
假设您从未见过此代码,并且您拥有运行这些类并消耗 100% CPU 的失控 Java 进程的 PID。
First let's start the StartThreads
class.
首先让我们开始StartThreads
上课。
$ ls
HeavyThread.java LightThread.java StartThreads.java
$ javac *
$ java StartThreads &
At this stage a Java process is running should be taking up 100 cpu. In my top I see:
在这个阶段,一个正在运行的 Java 进程应该占用 100 个 cpu。在我的顶部,我看到:
In top press Shift-H which turns on Threads. The man page for top says:
在顶部按 Shift-H 打开线程。top 的手册页说:
-H : Threads toggle
Starts top with the last remembered 'H' state reversed. When
this toggle is On, all individual threads will be displayed.
Otherwise, top displays a summation of all threads in a
process.
And now in my top with Threads display turned ON i see:
现在在我打开线程显示的顶部,我看到:
And I have a java
process with PID 28294
. Lets get the stack dump of this process using jstack
:
我有一个java
带有 PID的进程28294
。让我们使用以下方法获取此进程的堆栈转储jstack
:
$ jstack 28924
2010-11-18 13:05:41
Full thread dump Java HotSpot(TM) 64-Bit Server VM (17.0-b16 mixed mode):
"Attach Listener" daemon prio=10 tid=0x0000000040ecb000 nid=0x7150 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"DestroyJavaVM" prio=10 tid=0x00007f9a98027800 nid=0x70fd waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Thread-3" prio=10 tid=0x00007f9a98025800 nid=0x710d waiting on condition [0x00007f9a9d543000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at LightThread.run(LightThread.java:21)
at java.lang.Thread.run(Thread.java:619)
"Thread-2" prio=10 tid=0x00007f9a98023800 nid=0x710c waiting on condition [0x00007f9a9d644000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at LightThread.run(LightThread.java:21)
at java.lang.Thread.run(Thread.java:619)
"Thread-1" prio=10 tid=0x00007f9a98021800 nid=0x710b waiting on condition [0x00007f9a9d745000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at LightThread.run(LightThread.java:21)
at java.lang.Thread.run(Thread.java:619)
"Thread-0" prio=10 tid=0x00007f9a98020000 nid=0x710a runnable [0x00007f9a9d846000]
java.lang.Thread.State: RUNNABLE
at sun.security.provider.DigestBase.engineReset(DigestBase.java:139)
at sun.security.provider.DigestBase.engineUpdate(DigestBase.java:104)
at java.security.MessageDigest$Delegate.engineUpdate(MessageDigest.java:538)
at java.security.MessageDigest.update(MessageDigest.java:293)
at sun.security.provider.SecureRandom.engineNextBytes(SecureRandom.java:197)
- locked <0x00007f9aa457e400> (a sun.security.provider.SecureRandom)
at sun.security.provider.NativePRNG$RandomIO.implNextBytes(NativePRNG.java:257)
- locked <0x00007f9aa457e708> (a java.lang.Object)
at sun.security.provider.NativePRNG$RandomIO.access0(NativePRNG.java:108)
at sun.security.provider.NativePRNG.engineNextBytes(NativePRNG.java:97)
at java.security.SecureRandom.nextBytes(SecureRandom.java:433)
- locked <0x00007f9aa4582fc8> (a java.security.SecureRandom)
at java.util.UUID.randomUUID(UUID.java:162)
at HeavyThread.run(HeavyThread.java:27)
at java.lang.Thread.run(Thread.java:619)
"Low Memory Detector" daemon prio=10 tid=0x00007f9a98006800 nid=0x7108 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"CompilerThread1" daemon prio=10 tid=0x00007f9a98004000 nid=0x7107 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"CompilerThread0" daemon prio=10 tid=0x00007f9a98001000 nid=0x7106 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Signal Dispatcher" daemon prio=10 tid=0x0000000040de4000 nid=0x7105 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Finalizer" daemon prio=10 tid=0x0000000040dc4800 nid=0x7104 in Object.wait() [0x00007f9a97ffe000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00007f9aa45506b0> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:118)
- locked <0x00007f9aa45506b0> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:134)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159)
"Reference Handler" daemon prio=10 tid=0x0000000040dbd000 nid=0x7103 in Object.wait() [0x00007f9a9de92000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00007f9aa4550318> (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 <0x00007f9aa4550318> (a java.lang.ref.Reference$Lock)
"VM Thread" prio=10 tid=0x0000000040db8800 nid=0x7102 runnable
"GC task thread#0 (ParallelGC)" prio=10 tid=0x0000000040d6e800 nid=0x70fe runnable
"GC task thread#1 (ParallelGC)" prio=10 tid=0x0000000040d70800 nid=0x70ff runnable
"GC task thread#2 (ParallelGC)" prio=10 tid=0x0000000040d72000 nid=0x7100 runnable
"GC task thread#3 (ParallelGC)" prio=10 tid=0x0000000040d74000 nid=0x7101 runnable
"VM Periodic Task Thread" prio=10 tid=0x00007f9a98011800 nid=0x7109 waiting on condition
JNI global references: 910
From my top I see that the PID of the top thread is 28938
. And 28938
in hex is 0x710A
. Notice that in the stack dump, each thread has an nid
which is dispalyed in hex. And it just so happens that 0x710A
is the id of the thread:
从我的顶部,我看到顶部线程的 PID 是28938
. 而28938
在十六进制为0x710A
。请注意,在堆栈转储中,每个线程都有一个nid
以十六进制显示的。碰巧这0x710A
是线程的ID:
"Thread-0" prio=10 tid=0x00007f9a98020000 nid=0x710a runnable [0x00007f9a9d846000]
java.lang.Thread.State: RUNNABLE
at sun.security.provider.DigestBase.engineReset(DigestBase.java:139)
at sun.security.provider.DigestBase.engineUpdate(DigestBase.java:104)
at java.security.MessageDigest$Delegate.engineUpdate(MessageDigest.java:538)
at java.security.MessageDigest.update(MessageDigest.java:293)
at sun.security.provider.SecureRandom.engineNextBytes(SecureRandom.java:197)
- locked <0x00007f9aa457e400> (a sun.security.provider.SecureRandom)
at sun.security.provider.NativePRNG$RandomIO.implNextBytes(NativePRNG.java:257)
- locked <0x00007f9aa457e708> (a java.lang.Object)
at sun.security.provider.NativePRNG$RandomIO.access0(NativePRNG.java:108)
at sun.security.provider.NativePRNG.engineNextBytes(NativePRNG.java:97)
at java.security.SecureRandom.nextBytes(SecureRandom.java:433)
- locked <0x00007f9aa4582fc8> (a java.security.SecureRandom)
at java.util.UUID.randomUUID(UUID.java:162)
at HeavyThread.run(HeavyThread.java:27)
at java.lang.Thread.run(Thread.java:619)
And so you can confirm that the thread which is running the HeavyThread
class is consuming most CPU.
因此,您可以确认运行HeavyThread
该类的线程正在消耗大部分 CPU。
In read world situations, it will probably be a bunch of threads that consume some portion of CPU and these threads put together will lead to the Java process using 100% CPU.
在读取世界的情况下,可能是一堆线程占用了 CPU 的一部分,这些线程放在一起将导致 Java 进程使用 100% 的 CPU。
Summary
概括
- Run top
- Press Shift-H to enable Threads View
- Get PID of the thread with highest CPU
- Convert PID to HEX
- Get stack dump of java process
- Look for thread with the matching HEX PID.
- 跑顶
- 按 Shift-H 启用线程视图
- 获取 CPU 最高的线程的 PID
- 将 PID 转换为十六进制
- 获取java进程的堆栈转储
- 查找具有匹配 HEX PID 的线程。