【Android JNI】JNIEnv和JavaVM的区别
来源:互联网 发布:python字符串转字典 编辑:程序博客网 时间:2024/04/28 17:33
JNI的实现可涉及两个关键类:JNIEnv和JavaVM。
- JavaVM:这个代表java的虚拟机。所有的工作都是从获取虚拟机的接口开始的。
第一种方式,在加载动态链接库的时候,JVM会调用JNI_OnLoad(JavaVM* jvm, void* reserved)(如果定义了该函数)。第一个参数会传入JavaVM指针。
第二种方式,在native code中调用JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args)可以得到JavaVM指针。
两种情况下,都可以用全局变量,比如JavaVM* g_jvm来保存获得的指针以便在任意上下文中使用。
Android系统是利用第二种方式Invocation interface来创建JVM的。
- JNIEnv:JNI Interface Pointer, 是提供JNI Native函数的基础环境,线程相关,不同线程的JNIEnv相互独立。
JNIEnv只在当前线程中有效。本地方法不 能将JNIEnv从一个线程传递到另一个线程中。相同的 Java 线程中对本地方法多次调用时,传递给该本地方法的JNIEnv是相同的。但是,一个本地方法可被不同的 Java 线程所调用,因此可以接受不同的 JNIEnv。
JavaVM则可以在进程中的各线程间共享。理论上一个进程可以有多个JavaVM,但Android只允许一个(JavaVm and JIEnv)。需要强调的是JNIEnv是跟线程相关的。sdk文档中强调了do not cache JNIEnv*,要用的时候在不同线程中再通过JavaVM *jvm的方法来获取与当前线程相关的JNIEnv*。两者都可以理解为函数表(Function Pointer Table), 前者是使用Java程序创建的运行环境(从属于一个JVM)提供JNI Native函数。
- Java和Android中JavaVM对象有区别
在java里,每一个process可以产生多个java vm对象,但是在android上,每一个process只有一个Dalvik虚拟机对象,也就是在android进程中是通过有且只有一个虚拟器对象来服务所有java和c/c++代码。
Java 的dex字节码和c/c++的*.so同时运行Dalvik虚拟机之内,共同使用一个进程空间。之所以可以相互调用,也是因为有Dalvik虚拟机。当java 代码需要c/c++代码时,在Dalvik虚拟机加载进*.so库时,会先调用JNI_Onload(),此时就会把JAVA VM对象的指针存储于c层jni组件的全局环境中,在Java层调用C层的本地函数时,调用c本地函数的线程必然通过Dalvik虚拟机来调用c层的本地函数,此时,Dalvik虚拟机会为本地的C组件实例化一个JNIEnv指针,该指针指向Dalvik虚拟机的具体的函数列表,当JNI的c组件调用Java层的方法或者属性时,需要通过JNIEnv指针来进行调用。 当本地c/c++想获得当前线程所要使用的JNIEnv时,可以使用Dalvik虚拟机对象的JavaVM* jvm->GetEnv()返回当前线程所在的JNIEnv*。
附 JNIEnv和JavaVM的定义。他们位于头文件jni.h。$NDK\platforms\android-5\arch-arm\usr\include\jni.h的部分代码
- struct _JNIEnv;
- struct _JavaVM;
- #if defined(__cplusplus)
- typedef _JNIEnv JNIEnv; //C++使用这个类型
- typedef _JavaVM JavaVM; //C++使用这个类型
- #else
- typedef const struct JNINativeInterface* JNIEnv; //C使用这个类型
- typedef const struct JNIInvokeInterface* JavaVM; //C使用这个类型
- #endif
- struct JNINativeInterface
- {
- /****省略了的代码****/
- jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
- /****省略了的代码****/
- jobject (*GetStaticObjectField)(JNIEnv*, jclass, jfieldID);
- /****省略了的代码****/
- };
- struct _JNIEnv
- {
- const struct JNINativeInterface* functions;
- #if defined(__cplusplus)
- /****省略了的代码****/
- jmethodID GetMethodID(jclass clazz, const char* name, const char* sig)
- { return functions->GetMethodID(this, clazz, name, sig); }
- /****省略了的代码****/
- jobject GetStaticObjectField(jclass clazz, jfieldID fieldID)
- { return functions->GetStaticObjectField(this, clazz, fieldID); }
- /****省略了的代码****/
- #endif /*__cplusplus*/
- };
- struct JNIInvokeInterface
- {
- /****省略了的代码****/
- jint (*GetEnv)(JavaVM*, void**, jint);
- jint (*AttachCurrentThreadAsDaemon)(JavaVM*, JNIEnv**, void*);
- };
- struct _JavaVM
- {
- const struct JNIInvokeInterface* functions;
- #if defined(__cplusplus)
- /****省略了的代码****/
- 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*/
- };
0 0
- 【Android JNI】JNIEnv和JavaVM的区别
- Android底层JNI中的JavaVM和JNIEnv对象
- Android底层JNI中的JavaVM和JNIEnv对象
- JNIEnv和Dalvik的JavaVM的关系
- JNIEnv和Dalvik的JavaVM的关系
- Android JNI开发(1)--JavaVM和 JNIEnv 动态注册本地方法
- JavaVM和JNIEnv
- JavaVM和JNIEnv
- JNI系列(3):如何得到JavaVM,JNIEnv接口
- JNI完全指南(十)——JavaVM与JNIEnv
- jni的JNIEnv指针和jobject指针
- jni的JNIEnv指针和jobject指针
- Android JNI之JNIEnv
- android C++ 和 jni,根据JNIEnv的FindClass获取java类,包括多线程
- Android JNI 之 JNIEnv 解析
- Android JNI 之 JNIEnv 解析
- Android JNI 之 JNIEnv 解析
- Android JNI 之 JNIEnv 解析
- 2014-10-15工作
- 安卓第二课:教材中游戏启动界面实现之准备知识
- HTML5 标签列表
- 黑马程序员——面向对象11:组合
- UVA537
- 【Android JNI】JNIEnv和JavaVM的区别
- SQLite C/C++
- hdu1026(bfs+优先级队列)
- 100 条经典C语言笔试题目
- typedef input_iterator_tag iterator_category 这些都是什么意思?
- DES加密算法的实现(C++语言)
- MyBatis学习 之 一:MyBatis简介与配置MyBatis+Spring+MySql
- hadoop中fsimage和edits的区别
- android 中 系统日期时间的获取