NDK JNI JavaVM、JNIEnv和jobject的理解
JavaVM、JNIEnv和jobject的理解
三者特点:
1)JavaVM:能够跨越线程,能够跨越函数;
2)JNIEnv:不能跨越线程,否则奔溃,可以跨越函数;
3)jobject:不能跨越线程,否则奔溃,不能跨越函数,否则奔溃。
代码验证
1)java层native函数定义、在主线程和子线程调用验证
/*** java层主线程调用*/
public native void nativeFun0();
public native void nativeFun1();
/*** java层子线程调用*/
public native void nativeFun2();/*** 按钮点击事件*/
public void clickMethod0(View view) {nativeFun0();
}public void clickMethod(View view) {nativeFun1();
}public void clickMethod2(View view) {new Thread() {@Overridepublic void run() {super.run();nativeFun2(); // Java的子线程调用}}.start();
}
2)native层函数实现和native层函数子线程实现
// 定义全局javaVM,用于多线程使用
JavaVM *java_vm = nullptr;// 重写JNI_OnLoad函数,在执行System.loadLibrary时,调用该函数,在此进行动态注册
extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *javaVm, void *) {::java_vm = javaVm;return JNI_VERSION_1_6;
}/*** 在Java层主线程调用nativeFun0*/
extern "C"
JNIEXPORT void JNICALL
Java_com_ndk_thread_MainActivity_nativeFun0(JNIEnv *env, jobject thiz) {JavaVM *javaVm = nullptr;env->GetJavaVM(&javaVm);// 打印:当前函数env地址, 当前函数jvm地址, 当前函数job地址, JNI_OnLoad的jvm地址LOGE("Java层主线程 nativeFun0 当前函数env地址%p, 当前函数jvm地址:%p, 当前函数job地址:%p, JNI_OnLoad的jvm地址:%p\n",env, javaVm, thiz, ::java_vm);
}/*** 定义子线程的函数指针*/
void *run(void *) {JNIEnv *jniEnv = nullptr;// 在子线程附件一个jniEnv::java_vm->AttachCurrentThread(&jniEnv, nullptr);LOGE("native层子线程 run jvm地址:%p, 当前run函数的newEnv地址:%p \n", ::java_vm, jniEnv);// 释放::java_vm->DetachCurrentThread();return nullptr;
}/*** 在Java层主线程调用nativeFun1,native层调用子线程的函数指针*/
extern "C"
JNIEXPORT void JNICALL
Java_com_ndk_thread_MainActivity_nativeFun1(JNIEnv *env, jobject thiz) {JavaVM *javaVm = nullptr;env->GetJavaVM(&javaVm);// 打印:当前函数env地址, 当前函数jvm地址, 当前函数clazz地址, JNI_OnLoad的jvm地址LOGE("Java层主线程 nativeFun1 当前函数env地址%p, 当前函数jvm地址:%p, 当前函数clazz地址:%p, JNI_OnLoad的jvm地址:%p\n",env,javaVm, thiz, ::java_vm);// 创建子线程pthread_t pid;pthread_create(&pid, nullptr, run, nullptr);
}/*** 在Java层子线程调用nativeFun2*/
extern "C"
JNIEXPORT void JNICALL
Java_com_ndk_thread_MainActivity_nativeFun2(JNIEnv *env, jobject thiz) {JavaVM *javaVm = nullptr;env->GetJavaVM(&javaVm);// 打印:当前函数env地址, 当前函数jvm地址, 当前函数clazz地址, JNI_OnLoad的jvm地址LOGE("Java层子线程 nativeFun2 当前函数env地址%p, 当前函数jvm地址:%p, 当前函数clazz地址:%p, JNI_OnLoad的jvm地址:%p\n",env,javaVm, thiz, ::java_vm);
}
小结
查看打印log分析
![](/assets/blank.gif)
1)所有的JavaVM地址都是相同的,即JavaVM为同一个;
2)主线程的JNIEnv地址是相同,子线程的JNIEnv地址是不相同;
3)主线程的jobject地址是相同,子线程的jobject地址跟主线程是不相同;
结论:
1. JavaVM全局,绑定当前进程, 只有一个地址
2. JNIEnv线程绑定, 绑定主线程,主线程相同,故主线程地址相同;绑定子线程,多个子线程,故子线程地址不相同。
3. jobject 谁调用JNI函数,谁的实例会给jobject,如:MainActivity主线程调用地址指向MainActivity;子线程Thread程调用地址指向子线程Thread。
JNIEnv和jobject的崩溃解决:
JNIEnv:
使用全局的JavaVM附加当前异步线程 得到权限env操作。
JNIEnv *jniEnv = nullptr;
// 在子线程附件一个jniEnv
::java_vm->AttachCurrentThread(&jniEnv, nullptr);
// 释放
::java_vm->DetachCurrentThread();
jobject:
默认是局部引用,提升全局引用,可解决此问题。
env->NewGlobalRef(jobject); // 提升全局引用
NDK JNI JavaVM、JNIEnv和jobject的理解相关推荐
- C语言调用jni中JNIEnv指针使用和理解
使用C语言调用jni的时候,需要和java的环境对象和虚拟机对象交互.它们的C语言定义如下. typedef const struct JNINativeInterface* JNIEnv; type ...
- 【Android FFMPEG 开发】C++ 回调 Java 方法 模板 ( JavaVM *vm | JNIEnv *env | jobject instance | 引用类型 | 模板代码示例 )
文章目录 I . Native 调用 Java 方法 II . JNIEnv *env 与 jobject instance III . JavaVM *vm IV . 局部引用 与 全局引用 分析 ...
- android jni 中jnienv,android JNI中JNIEnv類型和jobject類型的解釋
JNIEXPORT void JNICALL Java_com_jni_demo_JNIDemo_sayHello (JNIEnv *env, jobject obj) { cout< } 對於 ...
- JNI学习笔记:JNIEnv、jobject与jclass详解
1 前言 2 JNIEnv指针 3 jobject与jclass类型 1 前言 在进行JNI编程开发的时候,使用javah生成Native方法对应的Native函数声明,会发现所有的Native函数的 ...
- 【Android 系统开发】Android JNI 之 JNIEnv 解析
. jni.h文件 : 了解 JNI 需要配合 jni.h 文件, jni.h 是 Google NDK 中的一个文件, 位置是 $/android-ndk-r9d/platforms/android ...
- JNI详解---从不懂到理解
Chap1:JNI完全手册... 3 Chap2:JNI-百度百科... 11 Chap 3:javah命令帮助信息... 16 Chap 4:用javah产生一个.h文件... 17 Chap ...
- Android JNI 之 JNIEnv 解析
jni.h文件 : 了解 JNI 需要配合 jni.h 文件, jni.h 是 Google NDK 中的一个文件, 位置是$/android-ndk-r9d/platforms/android-19 ...
- NDK JNI Android Studio开发与调试DEMO(三)(生成 .so 文件)
Android Studio NDK 开发与调试(生成 .so 文件) 温馨提示:如果你的 Android Studio 版本在 3.0以上 , 建议你用 cMake /ndk-build 的新姿势进 ...
- NDK JNI方式读写Android系统的demo(二)
NDK & JNI(方式读写Android系统的Demo) 大家都知道Android系统是一种基于Linux的自由及开放源码的操作系统,所以读写GPIO也可以直接用Linux那一套export ...
最新文章
- 任正非最新署名文章:不要因为美国打压而放弃全球化战略
- IOS中UITableView异步加载图片的实现
- boost::describe模块实现连载功能的测试程序
- Netty HTTP on Android
- halcon中面到面的距离_halcon学习笔记——(8)由标定板得到测量平面位姿-阿里云开发者社区...
- 9.广义霍夫变换——广义霍夫变换算法和识别中的应用、现在的霍夫算法及识别中的应用_2
- 【转】Unity利用WWW http传输Json数据
- android studio 上手使用 大水逼问题
- 机器学习- 吴恩达Andrew Ng Week4 神经网络Neural Networks知识总结
- 推荐一个js脚本的字体拟合模型
- 排名前三的网址导航站和源码资源站分享
- 9.郝斌C语言笔记——变量的作用域和存储方式
- 利用opencv 做一个疲劳检测系统(2)
- vscode英文感叹号没出现提示文本解决方法
- 设置oracle sys密码修改,Oracle修改SYS密码
- matlab has encountered,matlab运行程序时出现“matlab has encountered an internal problem
- PS四种扁平化设计风格-网摘
- Linux /centos7源码编译安装Nginx
- git did not exit cleanly (exit code 128)我个人解决方案
- Discuz招商加盟门户网站整站模板/加盟项目网站商业版源码/整站带测试数据
热门文章
- 二维码跳转不同的 app store
- 天刀各大服务器位置,天涯明月刀手游可以查看到好友所在区吗 好友服务器位置查看方法[多图]...
- 红旗Linux刻录到U盘,安装红旗Asianux_openEuler 8.1(欧拉版)的方法
- access中所有女生的记录,ACCESS建查询,如何查两个表里的内容
- 会员积分储值充值管理系统asp源码基于微信公众号
- 继承和实现区别java_java中继承和实现有什么区别,分别给程序带来了怎样的好处?...
- Deprecated API
- 《数字图像处理》题库5:计算题 ③
- 牛刀:2010年上海房价第一个开始下跌
- csv文件用Excel打开乱码如何处理