【Android 系统开发】Android JNI/NDK (三) 之 JNIEnv 解析
jni.h文件
: 了解 JNI 需要配合 jni.h 文件, jni.h 是 Google NDK 中的一个文件, 位置是 $/Android-ndk-r9d/platforms/android-19/arch-arm/usr/include/jni.h
;
1. JNIEnv 作用
JNIEnv 概念 : 是一个线程相关的结构体, 该结构体代表了 Java 在本线程的运行环境 ;
JNIEnv 与 JavaVM : 注意区分这两个概念;
-- JavaVM : JavaVM 是 Java虚拟机在 JNI 层的代表, JNI 全局只有一个;
-- JNIEnv
: JavaVM 在线程中的代表, 每个线程都有一个, JNI 中可能有很多个 JNIEnv;
JNIEnv 作用 :
-- 调用 Java 函数 : JNIEnv 代表 Java 运行环境, 可以使用 JNIEnv 调用 Java 中的代码;
-- 操作 Java 对象 : Java 对象传入 JNI 层就是 Jobject 对象, 需要使用 JNIEnv 来操作这个 Java 对象;
2. JNIEnv 的创建和释放
JNIEnv 创建 和 释放 : 从 JavaVM 获得 : 下面是 JavaVM 结构体的代码,
-- C语言 中来源 : JNIInvokeInterface 是 C 语言环境中的 JavaVM 结构体, 调用 (*AttachCurrentThread)(JavaVM*, JNIEnv**, void*) 方法, 可以获取 JNIEnv结构体;
-- C++ 中来源 : _JavaVM 是 C++ 中的 JavaVM 结构体, 调用 jint AttachCurrentThread(JNIEnv** p_env, void* thr_args) 方法, 可以获取 JNIEnv 结构体;
-- C语言 中释放 : 调用 JavaVM结构体 (JNIInvokeInterface) 中的 (*DetachCurrentThread)(JavaVM*)方法, 可以释放本线程中的 JNIEnv;
-- C++ 中释放 : 调用 JavaVM 结构体 (_JavaVM) 中的 jint DetachCurrentThread(){ return functions->DetachCurrentThread(this); }
方法, 即可释放 本线程中的 JNIEnv ;
/*
* JNI invocation interface.
*/
struct JNIInvokeInterface {
void* reserved0;
void* reserved1;
void* reserved2; jint (*DestroyJavaVM)(JavaVM*);
/* 创建 JNIEnv , 每个线程创建一个 */
jint (*AttachCurrentThread)(JavaVM*, JNIEnv**, void*);
/* 释放本线程的 JNIEnv */
jint (*DetachCurrentThread)(JavaVM*);
jint (*GetEnv)(JavaVM*, void**, jint);
jint (*AttachCurrentThreadAsDaemon)(JavaVM*, JNIEnv**, void*);
}; /*
* C++ version.
*/
struct _JavaVM {
const struct JNIInvokeInterface* functions; #if defined(__cplusplus)
jint DestroyJavaVM()
{ return functions->DestroyJavaVM(this); }
/* 创建 JNIEnv , 每个线程创建一个 , 调用的C语言结构提中的方法, C 与 C++ 方法相同 */
jint AttachCurrentThread(JNIEnv** p_env, void* thr_args)
{ return functions->AttachCurrentThread(this, p_env, thr_args); }
/* 释放本线程的 JNIEnv , 调用的C语言结构提中的方法, C 与 C++ 方法相同 */
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*/
};
3. JNIEnv 体系结构
线程相关 : JNIEnv 是线程相关的, 即 在 每个线程中 都有一个 JNIEnv 指针, 每个JNIEnv 都是线程专有的, 其它线程不能使用本线程中的 JNIEnv, 线程 A 不能调用
线程 B 的 JNIEnv;
JNIEnv 不能跨线程 :
--
当前线程有效 : JNIEnv 只在当前线程有效, JNIEnv 不能在 线程之间进行传递, 在同一个线程中, 多次调用 JNI层方法, 传入的 JNIEnv 是相同的;
--
本地方法匹配多JNIEnv : 在 Java 层定义的本地方法, 可以在不同的线程调用, 因此 可以接受不同的 JNIEnv;
JNIEnv 结构 : 由上面的代码可以得出, JNIEnv 是一个指针, 指向一个线程相关的结构, 线程相关结构指向 JNI 函数指针 数组, 这个数组中存放了大量的 JNI 函数指针, 这些指针指向了具体的 JNI 函数;
4. 分析 JNIEnv 相关代码
JNIEnv 定义的相关代码 :
<span style="font-family:Courier New;">/* 声明结构体, 以便在下面能够使用 */
struct _JNIEnv;
struct _JavaVM;
/* 声明 C 语言环境中的 JNIEnv 为 C_JNIEnv 指针, 指向 JNINativeInterface 结构体 */
typedef const struct JNINativeInterface* C_JNIEnv; #if defined(__cplusplus)
/* C++环境下, JNIEnv 是结构体 */
typedef _JNIEnv JNIEnv;
typedef _JavaVM JavaVM;
#else
/* C语言环境下, JNIEnv是指针 */
typedef const struct JNINativeInterface* JNIEnv;
typedef const struct JNIInvokeInterface* JavaVM;
#endif</span>
-- JNINativeInterface 结构体 : 该结构体中定义了大量的函数指针, 这些函数指针 指向 与 Java 相关的变量有关的函数, 如果是 C 语言环境中, JNIEnv 就是指向 该结构体的指针;
-- _JNIEnv 结构体 : C++ 环境中的 JNIEnv 就是该结构体, 该结构体中封装了 一个 JNINativeInterface 结构体指针, 即 C++ 中的 JNIEnv 要比 C 语言中的要多, 并且 完全兼容 C 语言中的 JNIEnv;
-- _JavaVM 结构体 : 该结构体 是 Java 虚拟机 在 JNI 中的代表, 整个 JNI 层 只存在一个 该 虚拟机映射;
JNINativeInterface 源码(删减过) : 省略后的, 其中定义了 与 Java 有关的相关方法, 都是 指向对应函数的函数指针;
-- 解析 JNIEnv* : C语言环境中的 typedef const struct JNINativeInterface* JNIEnv ,
JNIEnv* env 等价于 JNINativeInterface** env1 (指向结构体地址的指针), 要想 根据 二级指针 env1 获取 JNINativeInterface
结构体中定义的函数指针, 首先获取 指向结构体的一级指针, 获取方法是 (*env1), 因此调用其中的函数指针指向的方法要这样 : (*env1)->FindClass(JNIEnv*, const char*);
/*
* Table of interface function pointers.
*/
struct JNINativeInterface {
void* reserved0;
void* reserved1;
void* reserved2;
void* reserved3; jint (*GetVersion)(JNIEnv *); ... ... jobject (*NewDirectByteBuffer)(JNIEnv*, void*, jlong);
void* (*GetDirectBufferAddress)(JNIEnv*, jobject);
jlong (*GetDirectBufferCapacity)(JNIEnv*, jobject); /* added in JNI 1.6 */
jobjectRefType (*GetObjectRefType)(JNIEnv*, jobject);
};
_JNIEnv 源码(删减过) : 该源码中有一个 JNINativeInterface 结构体指针, 说明 C++ 环境的 JNIEnv 是在 C 语言环境的 JNIEnv 下扩展的;
--
解析 JNIEnv* : 定义是这样的 typedef _JNIEnv JNIEnv,
JNIEnv* env 等价于 _JNIEnv* env1, 因此调用 _JNIEnv 中定义的函数指针指向的函数的时候, 只需要 使用 env1->FindClass(JNIEnv*, const char*) 即可;
/*
* C++ object wrapper.
*
* This is usually overlaid on a C struct whose first element is a
* JNINativeInterface*. We rely somewhat on compiler behavior.
*/
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); } ... ... jlong GetDirectBufferCapacity(jobject buf)
{ return functions->GetDirectBufferCapacity(this, buf); } /* added in JNI 1.6 */
jobjectRefType GetObjectRefType(jobject obj)
{ return functions->GetObjectRefType(this, obj); }
#endif /*__cplusplus*/
};
【Android 系统开发】Android JNI/NDK (三) 之 JNIEnv 解析的更多相关文章
- Android系统开发--灯光系统之电池灯的流程分析
Android系统开发--Android灯光系统之电池灯的流程分析 前期系统准备 运行初始化,创建系统服务 创建电池服务,获得电池灯;创建监听者监听上报电池事件: mSystemServiceMana ...
- 《Android系统开发》笔记
<Android系统开发>笔记1:Android系统概述 Android四层架构: 1. Linux Kernel&driver层 a.依赖于Linux 2.6内核,包含安全性.内 ...
- 【Android 系统开发】CyanogenMod 13.0 源码下载 编译 ROM 制作 ( 手机平台 : 小米4 | 编译平台 : Ubuntu 14.04 LTS 虚拟机)
分类: Android 系统开发(5) 作者同类文章X 版权声明:本文为博主原创文章 ...
- Android系统开发实务实训
实训项目 : Android系统开发实务实训 项目成品名称: 绝地坦克 ...
- Android系统开发 编译系统签名的APP
前言 一般情况下,我们使用的签名都是自己生成的Java签名来编译APP. 但是,如果需要开发一些特定设备的APP(对权限有更高的要求,需求一些系统基本的权限,比如让APP可以控制设备的休眠),那就需要 ...
- Android 系统开发做什么?
题外话 18 年我从 Android 应用开发转 Framework 层开发了,从此开启了 996 幸福生活,博客技术文更新基本停滞了,被工作占据了过多的精力,实在没时间像以前一样拟稿.写作,实践.反 ...
- [课程设计]Scrum 3.1 多鱼点餐系统开发进度(第三阶段项目构思与任务规划)
Scrum 3.1 多鱼点餐系统开发进度(第三阶段项目构思与任务规划) 1.团队名称:重案组 2.团队目标:长期经营,积累客户充分准备,伺机而行 3.团队口号:矢志不渝,追求完美 4.团队选题:餐厅到 ...
- Scrum 3.1 多鱼点餐系统开发进度(第三阶段项目构思与任务规划)
Scrum 3.1 多鱼点餐系统开发进度(第三阶段项目构思与任务规划) 1.团队名称:重案组 2.团队目标:长期经营,积累客户充分准备,伺机而行 3.团队口号:矢志不渝,追求完美 4.团队选题:餐厅到 ...
- 【Android 系统开发】Android JNI 之 JNIEnv 解析
. jni.h文件 : 了解 JNI 需要配合 jni.h 文件, jni.h 是 Google NDK 中的一个文件, 位置是 $/android-ndk-r9d/platforms/android ...
随机推荐
- HDFS中Java的API使用测试
import java.io.IOException; import java.util.Arrays; import java.util.Date; import java.util.Scanner ...
- java.lang.ClassNotFoundException: com.*.listener.ConfigInfoReader
包的问题,删除掉了buildPath的包,再加上一个需要用的,问题搞定...不知道是为什么
- Allegro建立引脚封装概念名词梳理
首先感谢于博士的60讲的Cadence教学视频,老师讲的还是很有耐心,很细致,谢谢! 目前还只是看到建立PCB封装这一块,正好手头上有个案子在做,边做边学的进度还是要好很多.以前的工作对原理图这一块的 ...
- Java语言的多态性
用简单的话来描述Java:编译类型与运行类型不一致的时候就会出现多态! 下面一段代码可以用来描述Java多态 class BaseClass{ public String flag="父类的 ...
- Python OpenCV —— Modifying
一些索引和修改图像像素点数据等的操作,可打印观察运行结果. # -*- coding: utf-8 -*- """ Created on Wed Sep 28 00:11 ...
- 《JavaScript模式》第5章 对象创建模式
@by Ruth92(转载请注明出处) 第5章:对象创建模式 JavaScript 是一种简洁明了的语言,并没有其他语言中经常使用的一些特殊语法特征,如 命名空间.模块.包.私有属性 以及 静态成员 ...
- xmind的第五天笔记
- 【学习笔记】Oracle-1.安装及配置
Win7旗舰版安装Oracle_11gR1_database: http://my.oschina.net/laiwanshan/blog/89951 Oracle用户登陆 sqlplus sys/ ...
- Oracle学习系列7
Oracle学习系列7 ************************************************************************************ 关联表 ...
- [BZOJ 3503][Cqoi 2014]和谐矩阵
我觉得这一题的样例输出一点都不和谐,大家千万别像我一样被坑了…… 题目不算难,果然是进错省系列555,不过搞出 O(n*m*2m) 的还是不要挣扎的比较好 我们暴力地推出第 n 行 第 m 列中每个数 ...