JNI 引用与缓存

转载 2012年03月26日 22:47:08
全局引用/局部引用/弱全局引用
从java虚拟机创建的对象传到本地c/c++代码是会产生引用。根据java垃圾回收机制,只要有引用存在就不会触发引用指向的java对象的垃圾回收。
这些引用在JNI中分三种:
1、全局引用(Global Reference)
2、局部引用(Local Reference)
3、弱全局引用(Weak Global Reference)
---------------------------------------
1、局部引用(常用)基本上通过JNI返回来的引用都是局部引用。
例如:NewObject就会返回创建出来的实例的局部引用。局部应用只在该native函数中有效。所有在该函数中产生的局部引用,都会在函数返回的时候自动释放(freed),也可以使用DeleteLocalRef函数自动释放该引用
在局部引用的有效期中,可以传递到别的函数中,要强调的是他的有效期仍然只在一次的java本地函数调用中,所以千万不能用C++全局变量保存他或是把它定义为C++静态局部变量
2、全局引用
全局引用可以跨越当前线程,在多个native函数中有效,不过需要编程人员手动来释放该引用,全局引用存在期间会防止在java的垃圾回收的回收。
与局部引用不同,全局引用的创建不由JNI自动创建的,全局引用是需要调用NewGlobealRef函数,而释放他需要使用ReleaseGlobalRef函数。
3、弱全局引用
java1.2出来的功能,与全局引用相似,创建、删除都需要由编程人员来进行,这种引用全局引用一样,可以在多个本地代码有效,也跨越多线程有效,不过,这种引用将不会阻止垃圾回收器回收这个引用所指向的对象。
使用NewWeakGlobalRef跟ReleaseWeakGlobalRef来产生和解除引用。
关于引用的一些函数:
jobject NewGlobalRef(jobject obj);//创建全局引用
jobject NewLocalRef(jobject obj);//创建局部引用
jobject NewWeakGlobalRef(jobject obj);//创建弱全局引用
void DeleteGlobalRef(jobject obj);//删除全局引用
void DeleteLocalRef(jobject obj);//删除局部引用
void DeleteWeakGlobalRef(jobject obj);//删除弱全局引用
jboolean IsSameObject(jobject obj1,jobject obj2);//判断两个引用是否指向同一个java对象
这个函数对于弱全局引用有一个特别的功能,把Null传入要比较的对象中,就能够判断弱全局引用所指向的java对象是否被回收
----------------------------------------------------------------------
缓存:
缓存jfieldID/jmethodID
取得jfieldID跟jmethodID的时候会通过该属性/方法名加上签名来查询相应的jfieldID/jmethodID,这种查询相对开销较大,我们可以将这些FieldID/MethodID缓存起来,这样只需要查询一次,以后就使用缓存起来的FieldID/MethodID了
缓存的方式:
1、在使用的时候缓存(Caching at the Point of Use)
2、在Java类初始化时缓存(Caching at the Defining Class's Inititalizer)
----------------
在第一次使用的时候缓存:
在native code中使用static局部变量来保存已经查询过的ID,这样就不会在每次的函数调用时查询,而只要第一次查询成功后就保存起来了。
例子:JNIEXPORT void JNICALL Java_test_native(JNIEnv* env,jobject obj)
     {
        static jfieldID fieldID_string =NULL;
 jclass clazz=env->GetObjectClass(obj);
        if(fieldID_string==NULL)
 {
    fieldID_string=env->GetFieldID(class,"string","Ljava/lang/String;");
 }
 .......................
     }
---------------
在java类初始化的时候缓存
更好的方式就是在任何native函数调用前把id全部存起来。我们可以让java在第一次加载这类的时候首先调用本地代码初始化所有的jfieldID/jmethodID,这样的话就可以省去多次的确定id是否存在的语句,当然,这些jfieldID/jmethodID是定义在c/c++的全局。
使用这种方式还有好处,当java类卸载或是重新加载的手也会重新呼叫该本地代码来重新计算IDs。
例子:java类中:
public class TestNative
{
   static{ initNativeIDs();}
   static native void initNativeIDs();
   int propInt=0;
   String propStr="";
   public native void otherNative();
   public static void main(String[] args) {}
}
c/c++代码中:
jfieldID g_propInt_id=0;
jfieldID g_propStr_id=0;
JNIEXPORT void JNICALL
Java_TestNative_initNativeIDs(JNIEnv* env,jobject clazz)
{
   g_propInt_id=GetFieldID(clazz,"propInt","I");
   g_propStr_id=GetFieldID(clazz,"propStr","Ljava/lang/String;");
}
JNIEXPORT void JNICALL
Java_TestNative_otherNative(JNIEnv* env,jobject obj)
{
   //可以直接使用下g_propInt_id和g_propStr_id的值了
}
------------------------------------------------
使用JNI的两个弊端
1、使用JNI,那么这个Java Application将不能跨平台,如果要移植别的平台上,那么native代码就需要重新编写。
2、java是强类型的语言,而c/c++不是,因此你必须在写JNI时更小心
总之,必须在构建java程序的时候,尽量少使用本地代码

JNI/NDK开发指南(十)——JNI局部引用、全局引用和弱全局引用

转载请注明出处:http://blog.csdn.net/xyang81/article/details/44657385    这篇文章比较偏理论,详细介绍了在编写本地代码时三种引用的使用场景和注意...
  • xyang81
  • xyang81
  • 2015年04月04日 16:28
  • 8588

(五)JNI 引用、缓存

版权声明:本文为博主原创文章,未经博主允许不得转载。 本文纯个人学习笔记,由于水平有限,难免有所出错,有发现的可以交流一下。 一、JNI 引用C 通过 JNI 进行操作 java 的对象的方...
  • qq_18983205
  • qq_18983205
  • 2018年01月08日 21:50
  • 11

JNI中的全局引用、局部引用、弱全局引用 AND 缓存jfieldID和jmethodID的两种方法

JNI中的全局引用、局部引用、弱全局引用  AND 缓存jfieldID和jmethodID的两种方法 本文...
  • as371418912
  • as371418912
  • 2014年05月10日 15:52
  • 751

JNI引用与垃圾回收

本文转自http://hubingforever.blog.163.com/blog/static/171040579201221553444677/   本文转载整理自:  http://...
  • nicebooks
  • nicebooks
  • 2014年01月03日 11:30
  • 3709

Android NDK 开发(四)JNI 中局部引用、全局引用和弱全局引用

前言 做过Java的朋友都知道,内存管理这一块是完全透明的,new一个类的实例时,只知道创建完这个类的实例后,会返回这个实例的一个引用,然后拿着这个引用去访问它的成员了(属性、方法),完全不用管J...
  • u011974987
  • u011974987
  • 2016年10月18日 14:54
  • 618

Android NDK学习笔记6-JNI对引用数据类型的操作

字符串操作    JNI把Java字符串当成引用类型来处理,JNI提供了java字符串与C字符串之间相互转换的必要函数。因为java字符串对象是不可变的,因此JNI不提供任何修改现有的java字符串内...
  • mynameishuangshuai
  • mynameishuangshuai
  • 2016年09月22日 18:10
  • 1787

jni 调用共享SO库

JNI 调用SO 破解SO库
  • tiny_xie
  • tiny_xie
  • 2015年01月03日 02:40
  • 701

Android JNI出坑指南

本文来自于腾讯Bugly公众号(weixinBugly), 作者:qingcuilu,未经作者同意,请勿转载,原文地址:https://mp.weixin.qq.com/s/AtxEEN13z_sdb...
  • Tencent_Bugly
  • Tencent_Bugly
  • 2017年12月26日 09:44
  • 80

强应用 软引用 弱引用 虚应用 缓存

1、概述    在JDK1.2以前的版本中,当一个对象不被任何变量引用,那么程序就无法再使用这个对象。也就是说,只有对象处于可触及状态,程序才能使用它。这 就像在日常生活中,从商店购买了某样物品后,如...
  • vvv11222
  • vvv11222
  • 2014年09月01日 10:44
  • 358

android中JNI的调用生成头文件步骤

android 中通过JNI调用本地方法步骤介绍:首先是在eclipse中生成类文件 package Pag; public class JNI { static{ System.loadL...
  • u012083681
  • u012083681
  • 2014年03月10日 10:11
  • 1643
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:JNI 引用与缓存
举报原因:
原因补充:

(最多只允许输入30个字)