转自:  http://www.cnblogs.com/canphp/archive/2012/11/13/2768937.html

  JNIEnv是一个与线程相关的变量,不同线程的JNIEnv彼此独立。JavaVM是虚拟机在JNI层的代表,在一个虚拟机进程中只有一个JavaVM,因此该进程的所有线程都可以使用这个JavaVM。当后台线程需要调用JNI native时,在native库中使用全局变量保存JavaVM尤为重要,这样使得后台线程能通过JavaVM获得JNIEnv。(这句话引用了《深入理解Android卷1》第二章的内容)

native程序中频繁使用JNIEnv*和JavaVM*。而C和C++代码使用JNIEnv*和JavaVM*这两个指针的做法是有区别的,网上大部分代码都使用C++,基本上找不到关于C和C++在这个问题上的详细叙述。

在C中:

使用JNIEnv* env要这样      (*env)->方法名(env,参数列表)

使用JavaVM* vm要这样       (*vm)->方法名(vm,参数列表)

在C++中:

使用JNIEnv* env要这样      env->方法名(参数列表)

使用JavaVM* vm要这样       vm->方法名(参数列表)

  上面这二者的区别是,在C中必须先对env和vm间接寻址(得到的内容仍然是一个指针),在调用方法时要将env或vm传入作为第一个参数。C++则直接利用env和vm指针调用其成员。那到底C中的(*env)和C++中的env是否有相同的数据类型呢?C中的(*vm) 和C++中的vm是否有相同的数据类型呢?

为了验证上面的猜测,我们可以查看JNIEnv和JavaVM的定义。他们位于头文件jni.h。我开发JNI用的是android-5平台,下面是 $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*/
};

假如我们用C编码,宏__cplusplus没有定义,那么从最上面的宏#if defined(__cplusplus)可推断

  JNIEnv    代表类型 const struct JNINativeInterface*

  JavaVM   代表类型 const struct JNIInvokeInterface*

那么JNIEnv* env实际上等价于声明 const struct JNINativeInterface**  env

  JavaVM* vm实际上等价于声明 const struct JNIInvokeInterface ** vm

因此要调用JNINativeInterface结构体内的函数指针就必须先对env间接寻址。

(*env)的类型是const struct JNINativeInterface*(指向JNINativeInterface结构体的指针),这时候可以用这个指针调用结构体的成员函数指针,(*env)-> GetMethodID(env, jclass, const char*, const char*)。同理可分析JavaVM* vm。

----------------------------------------------------------------------------------------------------------------------------------------------

假如我们用C++编码,宏__cplusplus有定义,那么从最上面的宏#if defined(__cplusplus)可推断

  JNIEnv    代表类型 struct _JNIEnv

  JavaVM   代表类型 struct _JavaVM

那么JNIEnv* env实际上等价于声明 struct _JNIEnv*  env

  JavaVM* vm实际上等价于声明 struct _JavaVM* vm

要调用_JNIEnv结构体内的函数指针这直接使用env而不需间接寻址, env-> GetMethodID(jclass, const char*, const char*)。同理可分析JavaVM* vm。

现在可以回答刚才的猜测了,C中的(*env)类型是const struct JNINativeInterface*,C++中的env类型是struct _JNIEnv*,因此他们的数据类型不相同(虽然都是指针,但指向不同的结构体类型)。

我们再看结构体_JNIEnv(C++的JNIEnv所代表的类型),这个结构体内有一个成员const struct JNINativeInterface* functions,再仔细看_JNIEnv内定义的函数。当调用_JNIEnv内定义的函数时,其实就是通过functions这个指针调用JNINativeInterface内的函数指针,因此_JNIEnv的成员方法是JNINativeInterface的同名成员函数指针的包装而已,归根结底无论在C还是C++中其实都使用了JNINativeInterface结构体。这时调用JNINativeInterface的函数指针的第一参数是this,在C++中this代表指向当前上下文对象的指针其类型是struct _JNIEnv*(即JNIEnv*)。同理可分析_JavaVM。

NDK(13)JNIEnv和JavaVM的更多相关文章

  1. 【Android JNI】JNIEnv和JavaVM的区别

     JNI的实现可涉及两个关键类:JNIEnv和JavaVM. JavaVM:这个代表java的虚拟机.所有的工作都是从获取虚拟机的接口开始的.             第一种方式,在加载动态链接库的时 ...

  2. 第40篇-JNIEnv和JavaVM

    下面介绍2个与JNI机制相关的类型JNIEnv和JavaVM. 1.JNIEnv JNIEnv一般是是由虚拟机传入,而且与线程相关的变量,也就说线程A不能使用线程B的JNIEnv.而作为一个结构体,它 ...

  3. Jni 线程JNIEnv,JavaVM,JNI_OnLoad(GetEnv返回NULL?FindClass返回NULL?)

    此文章是关于NDK线程的第二篇理论知识笔记.主要有两个点,如下: 1.pthread_create(Too many arguements, expected 1) ?2.线程中如何获取JNIEnv? ...

  4. 第41篇-JNIEnv与JavaVM的初始化

    JavaVM和JNIEnv的初始化和JVM各模块的初始化都是在JNI_CreateJavaVM()函数中完成.这一篇将详细介绍JavaVM和JNIEnv的初始化过程. 1.初始化JavaVM Java ...

  5. 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 ...

  6. NDK开发之javaVM

    1.关于JNIEnv和JavaVM JNIEnv是一个与线程相关的变量,不同线程的JNIEnv彼此独立.JavaVM是虚拟机在JNI层的代表,在一个虚拟机进程中只有一个JavaVM,因此该进程的所有线 ...

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

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

  8. Android:JNI与NDK(一)

    友情提示:欢迎关注本人公众号,那里有更好的阅读体验以及第一时间获取最新文章 本篇目录 以下举例代码均来自:NDK示例代码 一.前言 安卓开发中很多场景需要用到NDK来开发,比如,音视频的渲染,图像的底 ...

  9. 继续研究NDK

    继续研究NDK 我在阿里云服务器上搭建了Android ndk的开发平台,并且借助这一平台研究了NDK的内部细节. NDK提供了Android本地编程的接口,让你可以开发高效的依赖库,提高程序的速度, ...

随机推荐

  1. Eclipse常用功能

    功能(Functions):内置运行java程序的插件(JDT:java develop tools)工作集(WorkSet)(Task list)计划任务管理器(Mylyn)系统配置(Prefere ...

  2. Android学习笔记:TabHost 和 FragmentTabHost(转)

    转自:http://www.cnblogs.com/asion/p/3339313.html   作者:Asion Tang   出处:http://asiontang.cnblogs.com   T ...

  3. Excel取消保护密码

    Excel表被保护了, 如果没有密码, 可通过以下宏代码查看 (Office 2013已测) Option Explicit Public Sub AllInternalPasswords()' Br ...

  4. Ubuntu 下为 Idea 创建启动图标.

    默认情况下,ubuntu将自动安装的软件快捷方式保存在/usr/share/applications目录下,如果我们要创建桌面快捷方式,需要在该目录下创建一个名为“Idea.desktop”的文件.通 ...

  5. HTML & XML 转义字符

    HTML & XML 转义字符 HTML中<, >,&等有特殊含义,(前两个字符用于链接签,&用于转义),不能直接使用.使用这三个字符时,应使用它们的转义序列,如下 ...

  6. 使用Lucene.net提升网站搜索速度整合记录

    1.随着网站数据量达到500万条的时候,发现SQL数据库如果使用LIKE语句来查询,总是占用CPU很忙,不管怎么优化,速度还是上不来; 2.经过网上收集资料,HUBBLE.net目前虽然做得不错,但需 ...

  7. angular入门系列教程4

    主题: 本篇主要目的就是继续完善home页下的index子页面的内容,处理一个列表,进行增删改查过滤等操作. 效果图: 细节: 主要的更改有两个,一个是修改模板index.html,还有就是增加控制器 ...

  8. UVA 12382 Grid of Lamps 贪心

    题目链接: C - Grid of Lamps Time Limit:1000MSMemory Limit: 0KB 问题描述 We have a grid of lamps. Some of the ...

  9. CSS基础知识学习笔记

    1.css基本样式讲解 1.1 css背景background-attachment:背景图像是否固定或者随着页面的其余部分滚动background-color:设置元素的背景颜色background ...

  10. jquery获取标签内容,编辑内容

    一.获取页面元素 三种方式获取页面中元素的内容. input标签使用:.val()获取 标签下的html及文本内容:.html() 仅获取标签下的纯文本内容:.text() <head> ...