JVMTI 调用 toString();在来自 C++ 代码的 Java 对象上

JVMTI Invoke toString(); on an Java object from C++ code

所以,我试图调用 toString();对象上的方法(在本例中为枚举)。这立即使我的应用程序崩溃。我假设,因为 toString();方法不是直接在枚举中声明,而是从对象 class(在本例中为枚举)继承而来,它无法找到该方法,因此会导致错误。

bool is_miss() {
    // the enum I want to invoke toString() on, the type() method works just fine and returns the jobject 
    jobject rt_type = type(); 
    // I assume that this is where i'm doing something wrong
    // Edit: My assumption was right, this is the line that causes the crash
    jmethodID method = m_jenv->GetMethodID(m_jenv->GetObjectClass(rt_type), "toString", "()Ljava/lang/String;");
    jstring str = (jstring)m_jenv->CallObjectMethod(rt_type, method);
    jboolean is_copy = jboolean{ true };
    return std::string(m_jenv->GetStringUTFChars(str, &is_copy));
}

如何声明 m_jenv:

JNIEnv* m_jenv;

这是初始化:

// ... other code ...
jsize count;
if (JNI_GetCreatedJavaVMs(&m_jvm, 1, &count) != JNI_OK || count == 0) {
    return;
}

jint res = m_jvm->GetEnv((void**)&m_jenv, JNI_VERSION_1_6);
if (res == JNI_EDETACHED) {
    res = m_jvm->AttachCurrentThread((void**)&m_jenv, nullptr);
}

if (res != JNI_OK) {
    return;
}
// ... other code ...

但是,初始化工作正常,m_jenv 字段是通过一个全局变量访问的,该变量包含一个包含 JNIEnv* 字段的 class。它被无数方法访问,甚至在 is_miss() 方法的 class 中也是如此,只有这个方法导致错误。

如何通过 JVMTI 在枚举(或一般的 Java 对象)上调用 toString 方法?

我已经做了一些试验,现在我找到了解决方案,所以它为什么不起作用是有道理的。

我没有尝试直接在 class 中查找 toString() 方法,而是通过了 class 在 java/lang/Enum 的 class 路径中找到的 class (或 java/lang/Object 对于 non-enum 类型)到 getMethodID() 函数。

jmethodID method = m_jenv->GetMethodID(m_jenv->FindClass("java/lang/Enum"), "toString", "()Ljava/lang/String;");

然后将我的 jobject 传递给 CallObjectMethod()。

jobject result = m_jenv->CallObjectMethod(rt_type, method);