Issue
The lambda that I pass to builder is populated into className object, and called at regular intervals (every hour) of time to refresh the other members. It gets called the first time successfully. I'm not sure if the lambda retains env, instance to legally call the reverse JNI function?
JNIEXPORT jint JNICALL
Java_com_company_app_ClassName_JniInit(JNIEnv *env, jobject instance){
int data = 0;
auto builder = new Builder(data,
[env, instance]() -> std::string {
std::string stringObj = populateData(env, instance); // This function makes a reverse JNI call to get data from a java function in the class
return stringObj;
}
);
std::shared_ptr<className> = builder->build();
return 1;
}
I seem to be getting a SIGNAL 11 error, SIGSEGV. Is this kind of segmentation fault catchable in any way, so the app doesn't crash?
Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x228 in tid 21785 (ClassName), pid 21573 (.company.app)
It seems to be crashing at this line inside populateData-
jstring data = (jstring)(env)->CallObjectMethod(instance, javaFunctionName);
Is there a way to check if this function will fail before calling it? I checked if env (JNIEnv* argument in populateData) is NULL, but its not, and has a valid address along with instance (jinstance argument in populateData).
Solution
To answer this question, I have found a slightly different kind of hack.
Don't copy the JNIEnv, and object or create references to them. They get deleted as soon as your JNI function goes out of scope. I'm not sure why copying doesn't work (if someone could answer this, that would be great). Alternatively, I've used JavaVM* to maintain a local reference of the jvm, you can do this in your JNI_OnLoad.
Use the function below, and it would work fine.
JavaVM* jvm; // Initialise this in OnLoad
JNIEnv *getJNIEnv()
{
JNIEnv *env = nullptr;
jint ret = jvm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6);
if (ret == JNI_EDETACHED || !env)
{
env = nullptr;
}
return env;
}
If you need the class instance, you'll need to initialise it via JNIEnv, but I use a static method for my class, so I just fetched the class using env->FindClass and then you can do env->GetStaticMethodID along with env->CallStaticObjectMethod.
Answered By - Ieshaan Saxena
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.