简体   繁体   中英

NullPointerException when Calling getFilesDir() in a JNI Call

I'm trying to call Java's getFilesDir() from a C library through a JNI call and I'm hitting a NullPointerException that I don't understand. Here's the exception:

W/System.err( 1576): java.lang.NullPointerException
W/System.err( 1576):    at android.content.ContextWrapper.getApplicationContext(ContextWrapper.java:109)
W/System.err( 1576):    at MYService.getFilesDirPath(MYService.java:1150)
W/System.err( 1576):    at MYService.UtvGetPeristentPath(Native Method)

The problem is happening in this function:

public String getFilesDirPath()
{
    try {
        return getFilesDir().getPath(); // <--- Exception happens here!
    }
    catch(Exception e)
    {
        e.printStackTrace();
        Log.e("DEBUG", "getFilesDirPath set exception", e);
        return null;
    }
}

The JNI call is set up with a few static variables that are set by JNI_OnLoad:

static JavaVM              *s_jvm = NULL;
static jclass cls; 
static jmethodID mid;
static jobject obj;                        

jint JNI_OnLoad(JavaVM *vm, void *reserved) {
    s_jvm = vm;
    JNIEnv *env;
    if (s_jvm){
        (*s_jvm)->AttachCurrentThread (s_jvm, &env, NULL);
    }    
    jclass localRef_class;
    jmethodID localRef_mid;
    jmethodID constr; 

    localRef_class = (*env)->FindClass(env, "MYService");
    cls = (*env)->NewGlobalRef(env,localRef_class);

    constr = (*env)->GetMethodID(env, cls, "<init>", "()V"); 
    obj = (*env)->NewGlobalRef(env, (*env)->NewObject(env, cls, constr));

    return JNI_VERSION_1_6; 
}

And here is the JNI function itself:

char *getFilesDirPath() {
    JNIEnv *jenv = NULL;
    __android_log_print(ANDROID_LOG_ERROR, "DEBUG", "JNI_Interface: getFilesDirPath");
    if(s_jvm == NULL)
    return NULL;

    int check = (*s_jvm)->GetEnv(s_jvm,(void **)&jenv,JNI_VERSION_1_6);

    if (check != JNI_OK) {
        (*s_jvm)->AttachCurrentThread(s_jvm, &jenv, NULL);
        (*s_jvm)->GetEnv(s_jvm,(void **)&jenv,JNI_VERSION_1_6);
    }
    if(jenv != NULL)
    {

        // get the method
        mid = (*jenv)->GetMethodID(jenv, cls, "getFilesDirPath", "()Ljava/lang/String;");
        if (mid == 0) {
            __android_log_print(ANDROID_LOG_ERROR, "DEBUG", "getFilesDirPath not found");
            if (check != JNI_OK)
                (*s_jvm)->DetachCurrentThread (s_jvm);
            return NULL;
        }
        else{
            jstring result = (jstring)(*jenv)->CallObjectMethod(jenv, obj, mid);
            char *filesDir = (char *) (*jenv)->GetStringUTFChars(jenv, result, 0);
            if (check != JNI_OK)
                (*s_jvm)->DetachCurrentThread (s_jvm);
            return filesDir;
        }

    }

    if (check != JNI_OK)
        (*s_jvm)->DetachCurrentThread (s_jvm);
    return NULL;
}

The problem is definitely tied to getFilesDir(). If I avoid calling that function and pass back a debug string, everything seems to work. I think the problem is related to not properly setting up the Context, but I'm not sure what might be wrong.

Your MYService class probably extends an Android Service or Activity. These classes are usually not created with their constructor call. They are started by the system using Intents. You can usually use their full 'Context' functionality for the first time in their onCreate methods. So you should get the reference to your MYService from somewhere else - not by instanciating it from JNI.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM