I am using JNI and JVMTI with C++ with the goal of printing all class names of a target java application. The problem I am experiencing is that it crashes when trying to call the getName() method from inside each Java class.
static jvmtiEnv* jvmtiEnv;
static JNIEnv* Env;
// The following code is located inside a method
jint class_count;
jclass* classes_ptr;
jvmtiEnv->GetLoadedClasses(&class_count, &classes_ptr);
Logger::Log("LoadedClassCount: " + std::to_string(class_count));
for (int i = 0; i < class_count; i++) {
jclass clazz = classes_ptr[i];
if (clazz) {
//Logger::Log("Class Number: " + std::to_string(i));
jmethodID mid_getName = Env->GetMethodID(clazz, "getName", "()Ljava/lang/String;");
if (!mid_getName) continue; // This method is not always available.
Logger::Log("Pass 2");
jobject classNameObj = Env->CallObjectMethod(clazz, mid_getName); // Crashes here
if (!classNameObj) continue;
Logger::Log("Pass 3");
// Printing fix suggested by @Someprogrammerdude
std::string str = Env->GetStringUTFChars((jstring) classNameObj, 0);
Logger::Log(("ClassName: " + str).c_str()); // or Logger::Log("ClassName: " + str)
}
}
Also yes, the fields jvmtiEnv, and Env are initialized and work because I have been able to call other methods but cant seem to figure out how to print class names. The following is my logging method. I also print log method calls to console that is actively attached to the target java application but since my code crashes this part is useless, so I rely on also printing to a txt file.
void Logger::Log(std::string message)
{
if (!Logger::Initialized) Logger::Init();
std::cout << "[ LOG ] :: " + message << std::endl;
std::ofstream log("C:\\Users\\me\\debug.txt", std::ofstream::app | std::ofstream::out);
log << message << std::endl;
}