jni那点事

今天说一下在jni开发中常另新手迷惑的JNIEnv这个东西

比如一个c语言的函数

JNIEXPORT jstring JNICALL Java_com_mmmmar_nativethread_MainActivity_native(JNIEnv *env, jobject obj){
    
  (*env)->newStringUTF("hello");

}

在这里为什么要用 (*env)->呢? 难道JNIEnv这个类型也是一个指针?

而在c++中却可以直接

JNIEXPORT jstring JNICALL Java_com_mmmmar_nativethread_MainActivity_native(JNIEnv *env, jobject obj){
    
  env->newStringUTF("hello");

}

这是怎么做到的呢?

我们来看一下jni.h中的一些定义

typedef _JNIEnv JNIEnv;

struct JNINativeInterface {
    void*       reserved0;
    void*       reserved1;
    void*       reserved2;
    void*       reserved3;

    jint        (*GetVersion)(JNIEnv *);
    jclass      (*DefineClass)(JNIEnv*, const char*, jobject, const jbyte*, jsize);
    jclass      (*FindClass)(JNIEnv*, const char*);
    .....等等一系列函数
}

struct _JNIEnv {
    /* do not rename this; it does not seem to be entirely opaque */
    const struct JNINativeInterface* functions;

#if defined(__cplusplus)

    jint GetVersion()
    { return functions->GetVersion(this); }

    jclass DefineClass(const char *name, jobject loader, const jbyte* buf,
        jsize bufLen)
    { return functions->DefineClass(this, name, loader, buf, bufLen); }

    jclass FindClass(const char* name)
    { return functions->FindClass(this, name); }
    ......等等一系列函数
#endif /*__cplusplus*/
};

我们需要关注的大致就是上边那些,其实把需要这些拿出来一看就很清楚了。

首先 typedef _JNIEnv JNIEnv 这个JNIEnv类型其实是_JNIEnv类型 ,而_JniEnv是一个结构体。

先看里边的第一项 const struct JNINativeInterface* functions 一个结构体的指针,在这个结果体里保存了Jni函数的地址,当我们需要调用jni函数时在最终会在这里找到函数的入口。

看到这里就可以明白(*env)->是什么意思了吧,它实际就等效于 (*env).functions-> 因为functions是结构的第一项,结构体指针的地址就是functions这个指针的地址。

再说在c++中的 env-> 问题,可以看到在_JNIEnv里有一个宏定义#if defined(__cplusplus) 在c++中,struct 实际是一个类,而那些jni函数被包装了一层,成为了_JNIEnv的成员函数

希望可以帮到一些刚接触jni的人,至少我刚接触时对这地方很困惑

上一篇:sqlserver游标


下一篇:Design Patterns in Android