NDK(13)JNIEnv和JavaVM
转自: 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的更多相关文章
- 【Android JNI】JNIEnv和JavaVM的区别
JNI的实现可涉及两个关键类:JNIEnv和JavaVM. JavaVM:这个代表java的虚拟机.所有的工作都是从获取虚拟机的接口开始的. 第一种方式,在加载动态链接库的时 ...
- 第40篇-JNIEnv和JavaVM
下面介绍2个与JNI机制相关的类型JNIEnv和JavaVM. 1.JNIEnv JNIEnv一般是是由虚拟机传入,而且与线程相关的变量,也就说线程A不能使用线程B的JNIEnv.而作为一个结构体,它 ...
- Jni 线程JNIEnv,JavaVM,JNI_OnLoad(GetEnv返回NULL?FindClass返回NULL?)
此文章是关于NDK线程的第二篇理论知识笔记.主要有两个点,如下: 1.pthread_create(Too many arguements, expected 1) ?2.线程中如何获取JNIEnv? ...
- 第41篇-JNIEnv与JavaVM的初始化
JavaVM和JNIEnv的初始化和JVM各模块的初始化都是在JNI_CreateJavaVM()函数中完成.这一篇将详细介绍JavaVM和JNIEnv的初始化过程. 1.初始化JavaVM Java ...
- 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 ...
- NDK开发之javaVM
1.关于JNIEnv和JavaVM JNIEnv是一个与线程相关的变量,不同线程的JNIEnv彼此独立.JavaVM是虚拟机在JNI层的代表,在一个虚拟机进程中只有一个JavaVM,因此该进程的所有线 ...
- 【Android 系统开发】Android JNI/NDK (三) 之 JNIEnv 解析
jni.h文件 : 了解 JNI 需要配合 jni.h 文件, jni.h 是 Google NDK 中的一个文件, 位置是 $/Android-ndk-r9d/platforms/android-1 ...
- Android:JNI与NDK(一)
友情提示:欢迎关注本人公众号,那里有更好的阅读体验以及第一时间获取最新文章 本篇目录 以下举例代码均来自:NDK示例代码 一.前言 安卓开发中很多场景需要用到NDK来开发,比如,音视频的渲染,图像的底 ...
- 继续研究NDK
继续研究NDK 我在阿里云服务器上搭建了Android ndk的开发平台,并且借助这一平台研究了NDK的内部细节. NDK提供了Android本地编程的接口,让你可以开发高效的依赖库,提高程序的速度, ...
随机推荐
- constructor(构造器)
当我们创建一个类的时候,如果不自定义构造器,则系统会自动创建一个默认的构造器,也是一个无参构造器用于初始化. 当我们在类的里面创建了自己的构造器,则系统将不会创建默认的构造器,由于需求条件不同,构造器 ...
- jquery ajax超时设置
var ajaxTimeoutTest = $.ajax({ url:'', //请求的URL timeout : 1000, //超时时间设置,单位毫秒 type : 'get', //请求方式 ...
- DIV+CSS高手必知的15个CSS常识
1.不要使用过小的图片做背景平铺.这就是为何很多人都不用 1px 的原因,这才知晓.宽高 1px 的图片平铺出一个宽高 200px 的区域,需要 200*200=40, 000 次,占用资源. 2.无 ...
- C# IL DASM 使用
IL DASM反编译工具 使用C#的猿人或多或少都会对微软的IL反编译工具(ildasm.exe)有所认识.我最早接触到这工具是公司同事使用他反编译exe程序,进行研读和修改.感觉他还是很强大. IL ...
- Oracle数据库表的备份和数据表的删除操作
--Oracle数据库中的表备份: --备份语句:在备份之后就可以将这张表的所有数据源删除了,但是之后有人对这张表的数据进行操作,但是在操作完成之后要记得将数据表恢复 CREATE TABLE DZH ...
- win8 ubuntu
点进去看到几点注意: 1. 如果Windows是UEFI方式安装的,那Ubuntu必须也用UEFI方式安装 2. 必须用64位的Ubuntu安装文件,32位的不能探测EFI 3. 必须用UEFI的方式 ...
- Root resource classes
Overview A root resource class is the entry point into a JAX-RS implemented RESTful Web service. It ...
- 转: 在.NET中操作数字证书
作者:玄魂出处:博客2010-06-23 12:05 http://winsystem.ctocio.com.cn/19/9492019.shtml .NET为我们提供了操作数字证书的两个主要的类,分 ...
- POJ 2240 Arbitrage(floyd)
http://poj.org/problem?id=2240 题意 : 好吧,又是一个换钱的题:套利是利用货币汇率的差异进行的货币转换,例如用1美元购买0.5英镑,1英镑可以购买10法郎,一法郎可以购 ...
- windows下eclipse远程连接hadoop错误“Exception in thread"main"java.io.IOException: Call to Master.Hadoop/172.20.145.22:9000 failed ”
在VMware虚拟机下搭建了hadoop集群,ubuntu-12.04,一台master,三台slave.hadoop-0.20.2版本.在 master机器上利用eclipse-3.3连接hadoo ...