1.区别
JavaVM:是java虚拟机环境,每个进程有且只有只有一个。
JNIEnv: 是线程上下文环境,每个线程只有一个,不能跨线程。
2.jni.h
2.1 jni头文件内部定义

从jni.h文件中可以看出,如果是C++,_JNIEnv JNIEnv和_JavaVM JavaVM分别用JNIEnv和JavaVM替换。如果是C,JNINativeInterface* JNIEnv和JNINativeInterface* JNIEnv分别定义成类型为JNINativeInterface和JNINativeInterface结构体指针JNIEnv和JNIEnv。
2.2 jni中C风格-----JNINativeInterface和JNINativeInterface
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 JNINativeInterface
/*
* 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和JNINativeInterface,_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());
}
网友评论