Skip to content
Advertisement

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

So, I was trying to invoke the toString(); method on an object (in this case an enum). This immediately crashed my application. I am assuming that, since the toString(); method isn’t declared directly in the enum but inherited from the Object class (Enum in this case) it is not able to find the method and therefore causes an error.

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));
}

How m_jenv is declared:

JNIEnv* m_jenv;

And it’s initialization:

// ... 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 ...

However, the initialization works and the m_jenv field is accessed through a global variable holding a class that holds the JNIEnv* field. It’s accessed by countless methods, even within the class of the is_miss() method and it’s only this method causing an error.

How would I invoke the toString method on a enum (or Java object in general) via JVMTI?

Advertisement

Answer

I have been experimenting a bit, and now that I found a solution it makes sense why it didn’t work.

Instead of trying to find the toString() method in the class directly, I passed the class found at the classpath of java/lang/Enum (or java/lang/Object for non-enum types) to the getMethodID() function.

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

And then just passed my jobject to CallObjectMethod().

jobject result = m_jenv->CallObjectMethod(rt_type, method);
8 People found this is helpful
Advertisement