jni如何判断两个jobject是否为同一个java对象
jni如何判断两个jobject是否为同一个java对象
jni开发时有时候需要将java对象缓存到native层,方便native层通过jni的反射方法进行回调操作。通常我们会将回调接口callback在native层存放为global reference全局引用,熟悉jni开发的都知道,jni传入到native 层的jobject生命周期仅仅是函数的生命周期,当jni函数返回后对应的jobject对象就会失效,不能再操作,所以就必须申请为global reference。
NewGlobalRef 将变量申请为全局引用,此时java虚拟机会保留jobject所指向的对象防止被垃圾回收器回收。 DeleteGlobalRef 释放全局引用,允许java虚拟机回收该引用指向的java对象,对于不需要使用的global reference必须调用该方法,否则会引起java虚拟机内存泄漏。
既然global reference的实质是指向java对象,那么我们在将某个变量声明为global reference时如何判断该jobject是否已经是当前设置的global reference呢。经过一番查询,看到了一下方法
IsSameObject 如果两个jobject指向同一个java 对象那么返回true,否则返回false。
既然有方法了,接下来就是验证工作了。
Hello.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class Hello */#ifndef _Included_Hello
#define _Included_Hello
#ifdef __cplusplus
extern "C" {
#endif
/** Class: Hello* Method: native_setObjectToGlobalRef* Signature: (LHello/Book;)V*/
JNIEXPORT void JNICALL Java_Hello_native_1setObjectToGlobalRef(JNIEnv *, jclass, jobject);/** Class: Hello* Method: native_release* Signature: ()V*/
JNIEXPORT void JNICALL Java_Hello_native_1release(JNIEnv *, jclass);#ifdef __cplusplus
}
#endif
#endif
Hello.cpp
#ifdef __cplusplus
extern "C" {
#endif#include <cstdio>
#include "Hello.h"// 全局变量,用于存储全局引用的
jobject g_book_ref = NULL; /** Class: Hello* Method: native_setObjectToGlobalRef* Signature: (LHello/Book;)V*/
JNIEXPORT void JNICALL Java_Hello_native_1setObjectToGlobalRef(JNIEnv *env, jclass jclazz, jobject jbook) {// 如果输入参数为null,那么不需要继续操作if (NULL == jbook) {printf("native_setObjectToGlobalRef jbook is NUll and g_book_ref is NOT NULL. we need to delete reference of old g_book_ref\n");if (NULL != g_book_ref) {env->DeleteGlobalRef(g_book_ref); // 删除老的全局引用g_book_ref = NULL;}return;}// 如果全局引用已经设置了,那么需要判断jni函数参数的jbook是否与当前的全局引用指向同一个java对象if (NULL != g_book_ref) {// 如果指向同一个对象,那么不需要再次为该jbook申请全局引用if (env->IsSameObject(g_book_ref, jbook)) {printf("native_setObjectToGlobalRef isSameObject: true, g_book_ref: %p, jbook: %p\n", g_book_ref, jbook);} else {// 如果指向不同对象,那么先释放老的全局引用,再为jbook申请全局引用printf("native_setObjectToGlobalRef isSameObject: false\n");printf("native_setObjectToGlobalRef g_book_ref and jbook is not same object. we need to delete reference of old g_book_ref\n");env->DeleteGlobalRef(g_book_ref);printf("native_setObjectToGlobalRef create global reference to g_book_ref\n");g_book_ref = env->NewGlobalRef(jbook);}} else {printf("native_setObjectToGlobalRef g_book_ref is NULL\n");printf("native_setObjectToGlobalRef create global reference to g_book_ref\n");g_book_ref = env->NewGlobalRef(jbook);}
}/** Class: Hello* Method: native_release* Signature: ()V*/
JNIEXPORT void JNICALL Java_Hello_native_1release(JNIEnv *env, jclass jclazz) {printf("native_release g_book_ref: %p\n", g_book_ref);if (NULL != g_book_ref) {env->DeleteGlobalRef(g_book_ref);g_book_ref = NULL;}
}#ifdef __cplusplus
}
#endif
Hello.java
public class Hello {static {try {String sysName = System.getProperty("os.name");if (sysName.contains("Linux")) {System.load(System.getProperty("user.dir") + "/libHello.so");} else if (sysName.contains("Drawin") || sysName.contains("Mac")) {System.load(System.getProperty("user.dir") + "/libHello.dylib");}} catch (java.lang.UnsatisfiedLinkError e) {e.printStackTrace();System.err.println("load so failed.");System.exit(1);}}static class Book {public String name;public Book() {}public Book(String name) {this.name = name;}}public native static void native_setObjectToGlobalRef(Book book);public native static void native_release();public static void main(String args[]) {Book b1 = new Book();Book b2 = new Book();System.out.println("set b1");native_setObjectToGlobalRef(b1);System.out.println("set b2");native_setObjectToGlobalRef(b2);System.out.println("##set b2");native_setObjectToGlobalRef(b2);System.out.println("##set null");native_setObjectToGlobalRef(null);native_release();}
}
makefile
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Darwin)
main:gcc -I"${JAVA_HOME}/include" -I"${JAVA_HOME}/include/darwin" Hello.cpp -dynamiclib -o libHello.dylib
endififeq ($(UNAME_S),Linux)
main:gcc -I"${JAVA_HOME}/include" -I"${JAVA_HOME}/include/linux" Hello.cpp -shared -fPIC -o libHello.so
endif
运行命令
$ make
$ javac Hello.java
运行程序
$ java -Djava.library.path=".:${JAVA_HOME}" Hello
输出结果
set b1
native_setObjectToGlobalRef g_book_ref is NULL
native_setObjectToGlobalRef create global reference to g_book_ref
set b2
native_setObjectToGlobalRef isSameObject: false
native_setObjectToGlobalRef g_book_ref and jbook is not same object. we need to delete reference of old g_book_ref
native_setObjectToGlobalRef create global reference to g_book_ref
##set b2
native_setObjectToGlobalRef isSameObject: true, g_book_ref: 0x7fb16ae08e90, jbook: 0x70000ce4a900
##set null
native_setObjectToGlobalRef jbook is NUll and g_book_ref is NOT NULL. we need to delete reference of old g_book_ref
native_release g_book_ref: 0x0
1. set b1时
因为是首次设置,此时native的g_book_ref还是null,没有被指向java对象,所以需要用全局引用为jbook保存java对象引用;
2. set b2时
isSameObject返回false,证明g_book_ref和jbook指向的对象不一样(此时jbook指向b2,而g_book_ref指向步骤1设置的b1),所以需要先删除老的b1全局引用再为b2申请全局引用;
3. 再次设置b2时
isSameObject返回true,证明g_book_ref和jbook指向的对象一样(此时jbook和g_book_ref都指向b2,注意两者的native地址不一样),为了节省操作,所以不需要在为jbook申请全局引用;
4. 设置为null
因为jbook为null,所以需要释放全局引用g_book_ref。
5. native释放
在Book native释放时因为步骤4已经提前释放了全局引用,所以不需要再释放了。
jni如何判断两个jobject是否为同一个java对象相关推荐
- DB2数据库 SQL语句判断两个日期 是否属于同一个季度
根据字段dsdate选择月份,以下语句可以判断一个月份的季度, SQL语句为: CASE WHEN SUBSTR(dsdate,6,2) BETWEEN 1 AND 3 THEN 1WHEN SUBS ...
- ping——判断两个设备是否在同一个局域网下
有时需要判断两个设备(有线/无线)是否在同一个局域网下面怎么操作呢? 一.ping简介 二.windows下 三.Linux下 四.注意事项 一.ping简介 ping 程序是对两台主机之间连通性进行 ...
- 如何判断两个IP地址是不是同一个网段(超实用)
IP地址 IP地址被用来给Internet上的电脑一个编号.大家日常见到的情况是每台联网的PC上都需要有IP地址,才能正常通信.我们可以把"个人电脑"比作"一台电话&qu ...
- c++ 实现计算立方体面积体积 并 判断两个立方体是否相等 (类和对象学习)
1.设计一个类 2.在私有权限内写立方体的属性 3.在公共权限内对立方体的属性进行可读可写操作 4.在类外定义一个bool类型的全局函数判断两个立方体是否相等 判断标准为:长宽高分别相等 code / ...
- 如何判断两个jq对象是同一个对象
如果说要判断是否同一对象,当然是用 === 来判断,但实际上两个不同的 jQuery 对象可能是对同一个/组 DOM 对象的封装,这个时候可以用 is 来判断,比如 var a = $(". ...
- 判断两个单链表是否相交--java实现
题目描述:单链表可能有环,也可能无环.给定两个单链表的头节点 head1 和 head2, 这两个链表可能相交,也可能不相交.请实现一个函数,如果两个链表相交,请返回相交 的第一个节点;如果不相交,返 ...
- 判断两棵二叉树是否相等(Java实现)
判断树是否相等,就是判断树中的每一个节点是否相等,根节点和根节点做比较,根节点的左子节点和左子节点作比较,右子节点和右子节点作比较,直到没有节点比较为止,中间只要一个节点不相等,就返回false,只有 ...
- Java中判断两个日期是否在同一个月
/*** 判断是否在同一个月** @return false:不在同一个月内,true在同一个月内*/public boolean isMonth(Date date1, Date date2) {C ...
- android 判断两个整数,【tips】判断两个整数是否是同一个数量级
iOS8沙盒路径的变化 iOS8中的的沙盒路径发生了变化 之前是这样的路径,通过NSHomedictionary()获取的家路径 /Users/wupeng/Library/Application S ...
- java 转xml 变成两根下划线_XStream将java对象转换为xml时,对象字段中的下划线“_”,转换后变成了两个...
使用XStream将java对象转换为xml时,需要对其中的一个字段加上CDATA,于是我自定义了一个XStream,主要代码如下:publicstaticXStreamcreateXstream() ...
最新文章
- 这可能是最简单易懂的机器学习入门
- iOS开发-简单工厂模式
- bug4 导入新工程时报 Target runtime com.genuitec.runtime.generic.jee60 is not defined
- matlab分类器设计,简单分类器的MATLAB实现.doc
- 软件调试学习笔记(三)—— 调试事件的处理
- 多个常见代码设计缺陷
- flutter webview浏览器及与js交互、打开第三方app
- 魔兽美服服务器维护,美服《魔兽世界》低人口密度服务器合并计划最新动态
- HDU1799 循环多少次?
- Swing 添加超链接 打开页面
- CodeMirror 多功能在线代码编辑器
- html中img显示旋转,css如何实现图片的旋转展示效果(代码示例)
- deepin上配置eclipse的hadoop开发环境
- CrossApp推出移动应用开发神器 CrossApp Style
- 华盛顿大学计算机专业gpa,以未决定专业进入大学再转计算机专业可行吗?
- 手机刷入面具_小米手机机型怎么刷入脸谱Magisk模块详细教程
- MATLAB将数据写入obj文件
- Java中的七种设计原则
- gsoc 任务_gsoc 2020火箭聊天React式全屏作曲家
- linux 查找替换
热门文章
- 操作系统课设 Nachos 实验二:Nachos 的 Makefiles
- 中科大和东北大学计算机考研,我国39所985高校,一共被分为五个档次,复旦大学处于第二档...
- 导入es数据_有道精品课实时数据中台建设实践
- linux文件系统与sysfs,Linux设备模型与Sysfs文件系统.doc
- 简单的ideatomcat热加载
- selenium-绕过登录
- JQuery的Ajax标准写法
- 使用DIME协议上传文件
- xtrabackup备份原理
- css之px自动转rem—“懒人”必备