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*。
 
建立全局的JavaVM的方法:
 //由java调用来建立JNI环境
JNIEXPORT void Java_com_nan_thread_MyThreadActivity_setJNIEnv( JNIEnv* env, jobject obj)
{
//保存全局JVM以便在子线程中使用
(*env)->GetJavaVM(env,&g_jvm);
//不能直接赋值(g_obj = obj)
g_obj = (*env)->NewGlobalRef(env,obj);
}

 获得JNIEvn方法:

 JNIEnv *JNI_GetEnv(int *attach) {
if (JNI_Jvm == NULL)
return NULL; int status; //判断是否有AttachCurrentThread
*attach = ; JNIEnv *_jniEnv = NULL; status = (*JNI_Jvm)->GetEnv(JNI_Jvm, (void **) &_jniEnv, JNI_VERSION_1_6); if (status == JNI_EDETACHED || _jniEnv == NULL) {
status = (*JNI_Jvm)->AttachCurrentThread(JNI_Jvm, &_jniEnv, NULL);
if (status < ) {
_jniEnv = NULL;
} else {
*attach = ;
}
}
return _jniEnv;
}

回收env:

 int JNI_DelEnv() {
if (JNI_Jvm == NULL)
return -; return (*JNI_Jvm)->DetachCurrentThread(JNI_Jvm);
}

在java线程中不能使用AttachCurrentThread、DetachCurrentThread方法来获取JNIEnv,否则会出错。

【Android JNI】JNIEnv和JavaVM的区别的更多相关文章

  1. [ 转载 ] Android JNI(一)——NDK与JNI基础

    Android JNI(一)——NDK与JNI基础 隔壁老李头 关注  4.4 2018.05.09 17:15* 字数 5481 阅读 11468评论 8喜欢 140 本系列文章如下: Androi ...

  2. Android JNI(一)——NDK与JNI基础

    本系列文章如下: Android JNI(一)——NDK与JNI基础 Android JNI学习(二)——实战JNI之“hello world” Android JNI学习(三)——Java与Nati ...

  3. NDK(5) Android JNI官方综合教程[JavaVM and JNIEnv,Threads ,jclass, jmethodID, and jfieldID,UTF-8 and UTF-16 Strings,Exceptions,Native Libraries等等]

    JNI Tips In this document JavaVM and JNIEnv Threads jclass, jmethodID, and jfieldID Local and Global ...

  4. 【Android 系统开发】Android JNI/NDK (三) 之 JNIEnv 解析

    jni.h文件 : 了解 JNI 需要配合 jni.h 文件, jni.h 是 Google NDK 中的一个文件, 位置是 $/Android-ndk-r9d/platforms/android-1 ...

  5. Android JNI 之 JNIEnv 解析

    jni.h文件 : 了解 JNI 需要配合 jni.h 文件, jni.h 是 Google NDK 中的一个文件, 位置是 $/android-ndk-r9d/platforms/android-1 ...

  6. 【Android 系统开发】Android JNI 之 JNIEnv 解析

    . jni.h文件 : 了解 JNI 需要配合 jni.h 文件, jni.h 是 Google NDK 中的一个文件, 位置是 $/android-ndk-r9d/platforms/android ...

  7. ZT ANDROID jni 中的事件回调机制JNIenv的使用 2012-09-10 12:53:01

    ANDROID jni 中的事件回调机制JNIenv的使用 2012-09-10 12:53:01 分类: 嵌入式 android framework 里java调用native,使用JNI机制,ja ...

  8. [转载]—— Android JNI知识点

    Java Native Interface (JNI)标准是java平台的一部分,它允许Java代码和其他语言写的代码进行交互.JNI 是本地编程接口,它使得在 Java 虚拟机 (VM) 内部运行的 ...

  9. 【转】android JNI

    原文网址:http://jinguo.iteye.com/blog/696185 Java Native Interface (JNI)标准是java平台的一部分,它允许Java代码和其他语言写的代码 ...

随机推荐

  1. mogodb(1) 简介

    1 引言 NoSQL,全称是“Not Only Sql”,指的是非关系型的数据库.这类数据库主要有这些特点:非关系型的.分布式.开源的.水平可扩展的.原始目的是为了大规模web应用,这场全新的数据库革 ...

  2. Python爬虫笔记(一)

    个人笔记,仅适合个人使用(大部分摘抄自python修行路) 1.爬虫Response的内容 便是所要获取的页面内容,类型可能是HTML,Json(json数据处理链接)字符串,二进制数据(图片或者视频 ...

  3. fastadmin iframe 表单提交之后跳转

    controller 对应的那个js文件中添加: define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function($, und ...

  4. 转:win32下的堆管理系统

    转:https://bbs.pediy.com/thread-224136.htm 准备刷漏洞战争中的堆溢出部分,但是对于堆的了解较少,在这里记录一下关于堆的学习记录,有错误请各位大大拍砖 参考: & ...

  5. (15) go 方法

  6. 爱奇艺全国高校算法大赛初赛A

    $01$背包. 数据范围:物品个数小于等于$3000$,背包大小小于等于$1000000$. $map<int,long long>dp$,用$map$去做$dp$,可以少遍历很多状态,可 ...

  7. Mutex 的正确打开方式

    在使用 Mutex 在给线程/进程间加锁时,需要注意的问题. 1 AbandonedMutexException 在使用 mutex.WaitOne 时,可能抛出异常 AbandonedMutexEx ...

  8. BZOJ1004 HNOI Cards

    第一次学习置换群这个东西. 这题需要利用Burnside定理. 即我们求出循环节为一(转完不变)的个数的平均数也就是等价类的个数. 定义:设G={a1,a2,…ag}是目标集[1,n]上的置换群.每个 ...

  9. [BZOJ4651][NOI2016]网格(Tarjan)

    下面直接给出结论,相关证明见官方题解. 1.若跳蚤数不超过1或仅有两只跳蚤且相邻,则答案为-1. 2.若跳蚤形成的连通块个数大于1,则答案为0. 3.若跳蚤之间建图存在割点,则答案为1. 4.否则为2 ...

  10. 数据离散化 ( 以及 stl 中的 unique( ) 的用法 )+ bzoj3289:Mato的文件管理

    http://blog.csdn.net/gokou_ruri/article/details/7723378 ↑惯例Mark大神的博客   bzoj3289:Mato的文件管理 线段树求逆序对+莫队 ...