如何在JVMTI中唯一标识线程

5

我正在开发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)的字段值。如何做到这一点?我可以遍历堆栈,但我无法获取字段名称。

有什么问题藏在其中还是你只是想分享你的经验? - specializt
你必须看标题。但是我肯定在文章中添加了问题。 - czs
这不是一个问题,而是一种陈述。此外:在内容中完全排除您实际的问题将确保您得到零回答。这不是某种博客或者论坛,人们想要帮助但也会拒绝这样做,如果您甚至无法组织一个简单的问题...大部分时间。 - specializt
2个回答

1

如你所指出的那样,一种解决方案是使用GetFieldName。这需要您查找jfieldid,这可能非常烦人。

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


那似乎是一个解决方案。如果回调方法(可能)在同一线程中调用,使用pthread_self()怎么样?我的早期测试表明它按预期工作。 - czs
我不明白为什么这也不是一个完全合理的解决方案 - 我认为从JVMTI出来,它将始终是相同的线程 - 这是支持调试器架构的要求,因为异步堆栈内省非常困难^^ - lscoughlin

1

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

由于进入/退出回调在同一线程中运行,因此可以使用 pthread_self() 并将其转换为例如 unsigned int。虽然名称更改,但您将获得线程的唯一编号,而不是在Java中找到的相同的 tid


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接