Reputation: 2500
I'm having problems with my FindClass call which returns null:
JData::JIgZorroBridgeClass = env->FindClass(JData::IgZorroBridgePath);
Most answers I find about this points to missing package name, or class loader issues.
IgZorroBridgePath here is my class with fully qualified package name, ie. com/igz/Zorro. Also as you can see I'm initializing the JVM right before this FindClass call, so I think I should be on the correct thread already.
Is there anything else I can check?
#include <assert.h>
#include "JNIHandler.hpp"
#include "JReferences.hpp"
const char* JVMClassPathOption = "-Djava.class.path=Plugin/ig/igplugin-0.1.jar";
const char* IgZorroBridgePath = "com/danlind/igz/ZorroBridge";
void JNIHandler::init()
{
initializeJVM();
initializeJavaReferences();
}
void JNIHandler::initializeJVM()
{
if(isJVMLoaded) return;
JavaVMInitArgs args;
JavaVMOption options[1];
args.version = JData::JNI_VERSION;
args.nOptions = 1;
args.options = options;
options[0].optionString = (char*)JData::JVMClassPathOption;
args.ignoreUnrecognized = JNI_FALSE;
jint res = JNI_CreateJavaVM(&jvm, (void **)&env, &args);
assert(res == JNI_OK);
isJVMLoaded = true;
}
JNIEnv* JNIHandler::getJNIEnvironment(){
return env;
}
JNIEnv* JNIHandler::getEnvForCurrentThread()
{
int envStat = jvm->GetEnv((void **)&env, JData::JNI_VERSION);
if (envStat == JNI_EDETACHED) {
jint res = jvm->AttachCurrentThread((void**)&env, NULL);
assert (res == JNI_OK);
}
return env;
}
void JNIHandler::initializeJavaReferences()
{
if(areJavaReferencesInitialized) return;
initExceptionHandling();
initBridgeObject();
registerNatives();
areJavaReferencesInitialized = true;
}
void JNIHandler::initBridgeObject()
{
JData::JIgZorroBridgeClass = env->FindClass(JData::IgZorroBridgePath);
checkJNIExcpetion(env);
registerClassMethods();
JData::JIgZorroBridgeObject = env->NewObject(JData::JIgZorroBridgeClass, JData::constructor.methodID);
checkJNIExcpetion(env);
}
void JNIHandler::initExceptionHandling()
{
JData::ExceptionClass = env->FindClass(JData::ExcPath);
JData::excGetName.methodID = env->GetMethodID(JData::ExceptionClass, JData::excGetName.name, JData::excGetName.signature);
}
void JNIHandler::registerNatives()
{
JData::JZorroClass = env->FindClass(JData::ZorroPath);
env->RegisterNatives(JData::JZorroClass, JData::nativesTable, JData::nativesTableSize);
checkJNIExcpetion(env);
}
void JNIHandler::registerClassMethods()
{
for(auto *desc : JData::igZorroBridgeMethods)
{
desc->methodID = env->GetMethodID(JData::JIgZorroBridgeClass, desc->name, desc->signature);
checkJNIExcpetion(env);
}
}
void JNIHandler::checkJNIExcpetion(JNIEnv* env)
{
jthrowable exc = env->ExceptionOccurred();
if (!exc) return;
jclass exccls(env->GetObjectClass(exc));
jstring name = static_cast<jstring>(env->CallObjectMethod(exccls, JData::excGetName.methodID));
char const* utfName(env->GetStringUTFChars(name, 0));
JData::excGetMessage.methodID = env->GetMethodID(exccls, JData::excGetMessage.name, JData::excGetMessage.signature);
jstring message = static_cast<jstring>(env->CallObjectMethod(exc, JData::excGetMessage.methodID));
char const* utfMessage(env->GetStringUTFChars(message, 0));
BrokerError(utfName);
BrokerError(utfMessage);
env->ReleaseStringUTFChars(message, utfMessage);
env->ReleaseStringUTFChars(name, utfName);
env->ExceptionClear();
}
Upvotes: 0
Views: 355
Reputation: 2500
I was using the spring boot maven plugin, which reshuffles the package structure. I switched to using the shade plugin instead, which doesn't move packages around. This enabled FindClass to find my java class.
Upvotes: 1