現在のJVMで実行中のすべてのスレッドのリストを取得する方法はありますか(クラスによって開始されたスレッドnotを含む)?
リスト内のすべてのスレッドのThread
およびClass
オブジェクトを取得することも可能ですか?
コードでこれを実行できるようにしたい
反復可能なセットを取得するには:
Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
次のように、ルートThreadGroup
へのハンドルを取得します。
ThreadGroup rootGroup = Thread.currentThread().getThreadGroup();
ThreadGroup parentGroup;
while ((parentGroup = rootGroup.getParent()) != null) {
rootGroup = parentGroup;
}
次に、ルートグループでenumerate()
関数を繰り返し呼び出します。 2番目の引数を使用すると、すべてのスレッドを再帰的に取得できます。
Thread[] threads = new Thread[rootGroup.activeCount()];
while (rootGroup.enumerate(threads, true ) == threads.length) {
threads = new Thread[threads.length * 2];
}
配列がすべてのエントリを格納するのに十分な大きさになるまでenumerate()を繰り返し呼び出す方法に注意してください。
はい、 スレッドのリストの取得 をご覧ください。そのページにはたくさんの例があります。
それはプログラムで行うことです。少なくともLinuxでリストが必要な場合は、次のコマンドを使用できます。
kill -3 processid
VMは、標準出力へのスレッドダンプを行います。
ThreadMXBean からスレッドに関する多くの情報を取得できます。
静的 ManagementFactory.getThreadMXBean() メソッドを呼び出して、MBeanへの参照を取得します。
jconsoleをご覧になりましたか?
これにより、特定のJavaプロセスに対して実行されているすべてのスレッドがリストされます。
JDK binフォルダーからjconsoleを起動できます。
WindowsでCtrl+Break
を押すか、Linuxでkill pid --QUIT
を送信することにより、すべてのスレッドの完全なスタックトレースを取得することもできます。
Groovyでは、プライベートメソッドを呼び出すことができます
// Get a snapshot of the list of all threads
Thread[] threads = Thread.getThreads()
Javaでは、セキュリティマネージャーで許可されている場合、リフレクションを使用してそのメソッドを呼び出すことができます。
次のようなものを試すことができます:
Thread.getAllStackTraces().keySet().forEach((t) -> System.out.println(t.getName() + "\nIs Daemon " + t.isDaemon() + "\nIs Alive " + t.isAlive()));
必要に応じて、明らかにより多くのスレッド特性を取得できます.
メインスレッドによって開始されたスレッドのリストを取得するコードスニペット:
import Java.util.Set;
public class ThreadSet {
public static void main(String args[]) throws Exception{
Thread.currentThread().setName("ThreadSet");
for ( int i=0; i< 3; i++){
Thread t = new Thread(new MyThread());
t.setName("MyThread:"+i);
t.start();
}
Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
for ( Thread t : threadSet){
if ( t.getThreadGroup() == Thread.currentThread().getThreadGroup()){
System.out.println("Thread :"+t+":"+"state:"+t.getState());
}
}
}
}
class MyThread implements Runnable{
public void run(){
try{
Thread.sleep(5000);
}catch(Exception err){
err.printStackTrace();
}
}
}
出力:
Thread :Thread[MyThread:2,5,main]:state:TIMED_WAITING
Thread :Thread[MyThread:0,5,main]:state:TIMED_WAITING
Thread :Thread[MyThread:1,5,main]:state:TIMED_WAITING
Thread :Thread[ThreadSet,5,main]:state:RUNNABLE
プログラムによって開始されていないシステムスレッドを含むすべてのスレッドが必要な場合は、以下の条件を削除します。
if ( t.getThreadGroup() == Thread.currentThread().getThreadGroup())
今出力:
Thread :Thread[MyThread:2,5,main]:state:TIMED_WAITING
Thread :Thread[Reference Handler,10,system]:state:WAITING
Thread :Thread[MyThread:1,5,main]:state:TIMED_WAITING
Thread :Thread[ThreadSet,5,main]:state:RUNNABLE
Thread :Thread[MyThread:0,5,main]:state:TIMED_WAITING
Thread :Thread[Finalizer,8,system]:state:WAITING
Thread :Thread[Signal Dispatcher,9,system]:state:RUNNABLE
Thread :Thread[Attach Listener,5,system]:state:RUNNABLE
Javaコンソールで、Ctrl-Breakを押します。すべてのスレッドに加えて、ヒープに関するいくつかの情報がリストされます。もちろん、これによってオブジェクトにアクセスすることはできません。しかし、とにかくデバッグには非常に役立ちます。
Apache Commonsユーザーは ThreadUtils
を使用できます。現在の実装では、前述のスレッドグループのウォークアプローチを使用しています。
for (Thread t : ThreadUtils.getAllThreads()) {
System.out.println(t.getName() + ", " + t.isDaemon());
}
public static void main(String[] args) {
// Walk up all the way to the root thread group
ThreadGroup rootGroup = Thread.currentThread().getThreadGroup();
ThreadGroup parent;
while ((parent = rootGroup.getParent()) != null) {
rootGroup = parent;
}
listThreads(rootGroup, "");
}
// List all threads and recursively list all subgroup
public static void listThreads(ThreadGroup group, String indent) {
System.out.println(indent + "Group[" + group.getName() +
":" + group.getClass()+"]");
int nt = group.activeCount();
Thread[] threads = new Thread[nt*2 + 10]; //nt is not accurate
nt = group.enumerate(threads, false);
// List every thread in the group
for (int i=0; i<nt; i++) {
Thread t = threads[i];
System.out.println(indent + " Thread[" + t.getName()
+ ":" + t.getClass() + "]");
}
// Recursively list all subgroups
int ng = group.activeGroupCount();
ThreadGroup[] groups = new ThreadGroup[ng*2 + 10];
ng = group.enumerate(groups, false);
for (int i=0; i<ng; i++) {
listThreads(groups[i], indent + " ");
}
}
ターミナルを使用してスレッドとその完全な状態のリストを取得するには、以下のコマンドを使用できます。
jstack -l <PID>
どのPIDがコンピューターで実行されているプロセスのIDです。 JavaプロセスのプロセスIDを取得するには、次のコマンドを実行するだけです。
jsp
また、TDA(スレッドダンプアナライザー)のjstackによって生成されたスレッドダンプを分析することもできます fastthread または spotifyスレッドアナライザーツール 。