Search code examples
androidandroid-ndkjava-native-interface

Getting error while GetEnv in JNI_OnLoad() and app crashing when removed these lines, error goes away


App is crashing in JNI_OnLoad(). I have checked the status it is zero. Still, the app is crashing. I want to create env variable to cache method IDs to use them for callback for java functions. I have tried caching jvm in context struct and doing same in callback() method but App is crashing. I am new bie to this concept. Can anybody explain what I am missing here.

Please find Attached code:

#include <jni.h>
#include <string>
#include "Numbers.h"

#include <android/log.h>

#define  LOG_TAG    "logs"

#define  LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)


typedef struct number_ctx{
    JavaVM  *javaVM;
    jclass   mathsClass;
    jobject  mathsObj;
    jclass   mainActivityClass;
    jobject  mainActivityObj;
    pthread_mutex_t  lock;
} NumbersCtx;
NumbersCtx g_ctx;

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
    JNIEnv* env;
    memset(&g_ctx, 0, sizeof(g_ctx));

    g_ctx.javaVM = vm;

    int status = vm ->GetEnv((void **)env, JNI_VERSION_1_6);

    LOGD("Status is %d ", status);
    if (vm ->GetEnv((void **)env, JNI_VERSION_1_6) != JNI_OK) {
        LOGD("Some error");
        return JNI_ERR; // JNI version not supported.
    }

    if(env->ExceptionCheck()) {
        env->ExceptionDescribe();
        env->ExceptionClear();
    }
    /*

    jclass  clz = env->FindClass(
                                    "com/example/maths/Maths1");
    g_ctx.mathsClass = static_cast<jclass>(env->NewGlobalRef(clz));

    jmethodID  jniHelperCtor = env->GetMethodID(g_ctx.mathsClass,
                                                   "printMessage", "()V");
    jobject    handler = env->NewObject(g_ctx.mathsClass,
                                           jniHelperCtor);
    g_ctx.mathsObj = env->NewGlobalRef(handler);

    g_ctx.mainActivityObj = NULL;*/
    return  JNI_VERSION_1_6;
}

void callback() {


}

Solution

  • You forgot to use the Address-Of operator (&) when calling GetEnv. GetEnv expects a pointer-to-a-pointer, but you're just passing it a pointer that you've cast to a pointer-to-a-pointer, which is not the same thing.

    So instead of

    vm ->GetEnv((void **)env, JNI_VERSION_1_6)
    

    you should be using

    vm ->GetEnv((void **)&env, JNI_VERSION_1_6)
    

    The end result of leaving out the Address-Of operator in this case is that GetEnv will store the JNIEnv* who-knows-where, and your env variable most likely won't contain a valid JNIEnv*.