JNIEnv与JavaVM区别

1.区别

JavaVM:是java虚拟机环境,每个进程有且只有只有一个。
JNIEnv: 是线程上下文环境,每个线程只有一个,不能跨线程。

2.jni.h

2.1 jni头文件内部定义

image.png

从jni.h文件中可以看出,如果是C++,_JNIEnv JNIEnv和_JavaVM JavaVM分别用JNIEnv和JavaVM替换。如果是C,JNINativeInterface* JNIEnv和JNINativeInterface* JNIEnv分别定义成类型为JNINativeInterface和JNINativeInterface结构体指针JNIEnv和JNIEnv。

2.2 jni中C风格-----JNINativeInterface和JNIInvokeInterface

2.2.1 JNINativeInterface

struct JNINativeInterface {
    jint        (*GetVersion)(JNIEnv *);

    jclass      (*DefineClass)(JNIEnv*, const char*, jobject, const jbyte*,
                        jsize);
    jclass      (*FindClass)(JNIEnv*, const char*);

    jmethodID   (*FromReflectedMethod)(JNIEnv*, jobject);
    jfieldID    (*FromReflectedField)(JNIEnv*, jobject);
    /* spec doesn't show jboolean parameter */
    jobject     (*ToReflectedMethod)(JNIEnv*, jclass, jmethodID, jboolean);
    jclass      (*GetSuperclass)(JNIEnv*, jclass);
    jboolean    (*IsAssignableFrom)(JNIEnv*, jclass, jclass);
    /* spec doesn't show jboolean parameter */
    jobject     (*ToReflectedField)(JNIEnv*, jclass, jfieldID, jboolean);
    jint        (*Throw)(JNIEnv*, jthrowable);
    jint        (*ThrowNew)(JNIEnv *, jclass, const char *);
    jthrowable  (*ExceptionOccurred)(JNIEnv*);
    void        (*ExceptionDescribe)(JNIEnv*);
    void        (*ExceptionClear)(JNIEnv*);
    void        (*FatalError)(JNIEnv*, const char*);
    ......
}

2.2.2 JNIInvokeInterface

/*
 * JNI invocation interface.
 */
struct JNIInvokeInterface {
    void*       reserved0;
    void*       reserved1;
    void*       reserved2;

    jint        (*DestroyJavaVM)(JavaVM*);
    jint        (*AttachCurrentThread)(JavaVM*, JNIEnv**, void*);
    jint        (*DetachCurrentThread)(JavaVM*);
    jint        (*GetEnv)(JavaVM*, void**, jint);
    jint        (*AttachCurrentThreadAsDaemon)(JavaVM*, JNIEnv**, void*);
};

2.3 jni中C++风格-----_JNIEnv和_JavaVM

2.3.1_JNIEnv

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); }

    jmethodID FromReflectedMethod(jobject method)
    { return functions->FromReflectedMethod(this, method); }

    jfieldID FromReflectedField(jobject field)
    { return functions->FromReflectedField(this, field); }

    jobject ToReflectedMethod(jclass cls, jmethodID methodID, jboolean isStatic)
    { return functions->ToReflectedMethod(this, cls, methodID, isStatic); }

    jclass GetSuperclass(jclass clazz)
    { return functions->GetSuperclass(this, clazz); }

    jboolean IsAssignableFrom(jclass clazz1, jclass clazz2)
    { return functions->IsAssignableFrom(this, clazz1, clazz2); }
    ........
}

2.3.2 _JavaVM

/*
 * C++ version.
 */
struct _JavaVM {
    const struct JNIInvokeInterface* functions;

#if defined(__cplusplus)
    jint DestroyJavaVM()
    { return functions->DestroyJavaVM(this); }
    jint AttachCurrentThread(JNIEnv** p_env, void* thr_args)
    { return functions->AttachCurrentThread(this, p_env, thr_args); }
    jint DetachCurrentThread()
    { return functions->DetachCurrentThread(this); }
    jint GetEnv(void** env, jint version)
    { return functions->GetEnv(this, env, version); }
    jint AttachCurrentThreadAsDaemon(JNIEnv** p_env, void* thr_args)
    { return functions->AttachCurrentThreadAsDaemon(this, p_env, thr_args); }
#endif /*__cplusplus*/
};

2.4 结论

通过JNINativeInterface和JNIInvokeInterface,_JNIEnv 和_JavaVM可以看出C和C++的写法在JNI中不一样。_JNIEnv和_JavaVM实际上是对JNINativeInterface和JNIInvokeInterface分别进行一层封装。最终调用还是C风格中结构体方法。

3.C与C++ JNI风格实例

通过上面分析可以看出C与C++ JNI风格写法不同

3.1 C风格

JNIEXPORT jstring JNICALL Java_jni_chowen_com_nativeapp_MainActivity_signture (JNIEnv *env, jobject jobject1, jstring jstring1) {
    //md5加密
    const char *jcstr = (env)->GetStringUTFChars(jstring1, 0);
    MD5 md5;
    md5.update(jcstr);
    string jstring2 = md5.toString();

    //package_name
    jstring packName = getPackname(env, jobject1, jobject1);
    const char *c = env->GetStringUTFChars(packName, 0);
    LOGE("getPackageName: %s", c);

    //signature
    jstring signatures = getSignature(env, jobject1, jobject1);
    const char *signaturesc = env->GetStringUTFChars(signatures, 0);
    LOGE("signatures: %s", signaturesc);
  return (*env)->NewStringUTF(env, jstring2.c_str());
}

3.2 C++风格

JNIEXPORT jstring JNICALL Java_jni_chowen_com_nativeapp_MainActivity_signture (JNIEnv *env, jobject jobject1, jstring jstring1) {
    //md5加密
    const char *jcstr = (env)->GetStringUTFChars(jstring1, 0);
    MD5 md5;
    md5.update(jcstr);
    string jstring2 = md5.toString();

    //package_name
    jstring packName = getPackname(env, jobject1, jobject1);
    const char *c = env->GetStringUTFChars(packName, 0);
    LOGE("getPackageName: %s", c);

    //signature
    jstring signatures = getSignature(env, jobject1, jobject1);
    const char *signaturesc = env->GetStringUTFChars(signatures, 0);
    LOGE("signatures: %s", signaturesc);
  return env->NewStringUTF(jstring2.c_str());
}

你可能感兴趣的:(JNIEnv与JavaVM区别)