JNI returns 同一逻辑 Java 对象的不同作业项目

JNI returns different jobjects for the same logical Java object

我需要获取当前线程,但是java对象Thread,而不是windows内核GetCurrentThread()。 但我有这个问题: 代码:

void MyTest(JNIEnv* env) {
    jobject t1 = GetJavaCurrentThread(env);
    jobject t2 = GetJavaCurrentThread(env);

    if (t1 != t2) {
        std::cout << "this shouldn't happen. some informations:" << endl;
        std::cout << t1 << " " << t2 << endl;
        std::cout << GetJavaThreadName(env, t1) << " " << GetJavaThreadName(env, t2) << endl;
    }
}

jobject GetJavaCurrentThread(JNIEnv* env) {
    jclass threadClass = env->FindClass("java/lang/Thread");
    jmethodID currentThreadMtd = env->GetStaticMethodID(threadClass, "currentThread", "()Ljava/lang/Thread;");
    return env->CallStaticObjectMethod(threadClass, currentThreadMtd);
}

const char* GetJavaThreadName(JNIEnv* env, jobject thread) {
    jclass threadClass = env->FindClass("java/lang/Thread");
    jmethodID getNameMtd = env->GetMethodID(threadClass, "getName", "()Ljava/lang/String;");
    jstring name = (jstring) env->CallObjectMethod(thread, getNameMtd);
    return env->GetStringUTFChars(name, NULL);
}

日志:

为什么我从 jni 调用 Thread.currentThread 得到不同的对象?

也许这是获取 java 端线程的错误方法?

JNI 规范在局部引用的主题上有这样的说法,这是您从 CallStaticObjectMethod:

等函数中得到的结果

To implement local references, the Java VM creates a registry for each transition of control from Java to a native method. A registry maps nonmovable local references to Java objects, and keeps the objects from being garbage collected. All Java objects passed to the native method (including those that are returned as the results of JNI function calls) are automatically added to the registry. The registry is deleted after the native method returns, allowing all of its entries to be garbage collected.

There are different ways to implement a registry, such as using a table, a linked list, or a hash table. Although reference counting may be used to avoid duplicated entries in the registry, a JNI implementation is not obliged to detect and collapse duplicate entries.

这意味着允许实现为您提供对同一 Thread 对象的两个单独的本地引用。 如果要测试对象相等性,请使用 JNI IsSameObject method:

jboolean areEqual = env->IsSameObject(t1, t2);