小编典典

在Linux中获取Java线程的线程ID

linux

我有一个Java应用程序,其中创建了一些线程(通过new Thread())。通过使用,ps我可以看到它们具有不同的线程ID(LWP列),我想从Java应用程序中获取这些ID。

在我发现的与此主题相关的大多数文章中,解决方案是使用ManagementFactory.getRuntimeMXBean().getName()

但是,使用该方法可以为我提供主线程的PID(即使我从其中一个线程调用它),因此它并不能真正解决我的问题。

有什么方法可以获取Thread应用程序创建的每个线程的线程ID ?

是否可以使用JNI完成它?如果我可以以某种方式连接到可以调用的C函数syscall(__NR_gettid),那可以解决我的问题。我真的不在乎可移植性,因此我对只适用于Linux机器的解决方案完全没问题。

更新: 我实际上已经通过使用JNI解决了我的问题。详细信息在我的答案中进行了解释。谢谢大家的建议/评论。


阅读 761

收藏
2020-06-02

共1个答案

小编典典

最后,我发现JNI方法是解决我的问题的最佳方法。作为参考,我发布了代码并为其构建了说明(基于Wikipedia
示例):

负责连接C代码的Java类(GetThreadID.java):

public class GetThreadID {
    public static native int get_tid();

    static {
        System.loadLibrary("GetThreadID");
    }
}

负责获取线程ID(GetThread.c)的C文件:

#include <jni.h>
#include <syscall.h>
#include "GetThreadID.h"

JNIEXPORT jint JNICALL
Java_GetThreadID_get_1tid(JNIEnv *env, jobject obj) {
    jint tid = syscall(__NR_gettid);
    return tid;
}

有关如何使用GetThreadID类的示例:

class Main {
    public static void main(String[] args) {
        int tid = GetThreadID.get_tid();
        System.out.println("TID=" + tid);
    }
}

最后,构建说明(javah自动生成GetThreadID.h):

JAVA_HOME=$(readlink -f /usr/bin/javac | sed "s:bin/javac::")
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
javac GetThreadID.java
javah GetThreadID

gcc -I${JAVA_HOME}/include -fPIC -shared GetThreadID.c -o libGetThreadID.so
javac Main.java
java Main
2020-06-02