I'm new in JNI and c++. I have some api that required shared pointer with some handler to subscribe on some messages. I can call required method in my handler in "main" c++ method, but when I call it from c++ wrapper I get JVM error and my application crash. My native method is next:
public native int subscribe(Handler handler);
Java Handler class:
public class Handler {
public void call(String m1, String m2) {
System.out.println("call: " + m1 + " " + m2);
}
}
JNI implementation:
JNIEXPORT jint JNICALL Java_com_lib_NativeClient_subscribe (JNIEnv* env, jobject thisObj, jobject javaHandler) {
jclass handlerClass = env->GetObjectClass(javaHandler);
jmethodID call = env->GetMethodID(handlerClass, "call", "(Ljava/lang/String;Ljava/lang/String;)V");
const std::string &message1 = "message1";
const std::string &message2 = "message2";
jstring javMessage1 = env->NewStringUTF((const char* )message1.c_str());
jstring javMessage2 = env->NewStrbingUTF((const char* )message2.c_str());
env->CallVoidMethod(javaHandler, call, javMessage1, javMessage2);
JavaWrapperHandler javaWrapperHandler = JavaWrapperHandler(env, javaHandler);
std::shared_ptr<JavaWrapperHandler> handlerSharedPointer = std::make_shared<JavaWrapperHandler>(javaWrapperHandler);
return some::lib::subscribe(handlerSharedPointer);
};
All works fine, I call 'call' method with this code. But I need to call this method after I subscribe to messages, I.e. Subject will call it. I write c++ wrapper for my java class to pass it to subscribe method:
class JavaWrapperHandler : public some::lib::Handler {
JNIEnv* env;
jobject javaHandler;
public:
JavaWrapperHandler(JNIEnv* genEnv, jobject handler) {
env = genEnv;
javaHandler = env->NewGlobalRef(handler);
}
~JavaWrapperHandler() {
env->DeleteGlobalRef(javaHandler);
}
virtual void call(const std::string &message1, const std::string &message2) {
jclass handlerClass = env->GetObjectClass(javaHandler);
jmethodID call = env->GetMethodID(handlerClass, "call", "(Ljava/lang/String;Ljava/lang/String;)V"); // Here I get error
jstring javMessage1 = env->NewStringUTF((const char* )message1.c_str());
jstring javMessage2 = env->NewStringUTF((const char* )message2.c_str());
env->CallVoidMethod(javaHandler, call, javMessage1, javMessage2);
};
};
When Subject call 'call' method I receive JVM error:
A fatal error has been detected by the Java Runtime Environment:
SIGSEGV (0xb) at pc=0x7694d8a4, pid=5681, tid=5702
JRE version: OpenJDK Runtime Environment (Zulu11.31+16-CA) (11.0.3+7) (build 11.0.3+7-LTS) Java VM: OpenJDK Client VM (11.0.3+7-LTS, mixed mode, serial gc, linux-arm) Problematic frame: V [libjvm.so+0x3e58a4] get_method_id(JNIEnv_, _jclass, char const*, char const*, bool, Thread*) >>[clone .isra.149]+0x288
What is wrong? Thanks in advance.