jvmti中如何唯一标识线程

How to uniquely identify thread in jvmti

我正在研究 JVMTI 代理,我想在方法进入和退出时识别相同的线程。我能够获取线程名称,但这还不够。

假设您有这样的方法:

public class Main {
    public static void myMethod() {
        System.out.println("doing something as " + Thread.currentThread().getName());
        Thread.currentThread().setName("SomethingDifferent");
        System.out.println("doing something as same thread " + Thread.currentThread().getName());
    }
}

所以进入这个方法将有一个名字和退出这个线程有不同的名字。

像这样使用 JVMTI 时:

static void JNICALL callback_on_method_entry(jvmtiEnv *jvmti, JNIEnv* env,
    jthread thread, jmethodID method)
{
    ...
    (*jvmti)->GetThreadInfo(jvmti, thread, &info);
    ...
}

static void JNICALL callback_on_method_exit(jvmtiEnv *jvmti, JNIEnv *env, jthread thread, jmethodID method, jboolean was_popped_by_exception, jvalue return_value)
{
    ...
    (*jvmti)->GetThreadInfo(jvmti, thread, &info);
    ...
}

每个 info 将报告不同的线程名称,我希望它们具有相同的标识符。

如何为线程获取相同的标识符?

一种解决方案是获取引用的 Thread (tid) 的字段值。 怎么做 ?我可以遍历堆,但我无法获取字段名称。

正如您所指出的,一种解决方案是使用 GetFieldName。这需要您查找 jfieldid,这真的很烦人。

我见过其他人这样做的方式是简单地分配他们自己的 ID 并将其存储在线程本地存储中。请参阅 UofO 的 TAU 项目中的 JavaThreadLayer.cpp,特别是 JavaThreadLayer::GetThreadId() 函数。

我终于找到了另一个简单的解决方案:

因为 entry/exit 回调在同一个线程中 运行,所以可以使用 pthread_self() 并进行转换,例如至 unsigned int。它与您在 java 中找到的 tid 不同,但您将获得线程的唯一编号,尽管名称已更改。