JNI学习笔记——JAVA持久化C++对象

问题

当我们需要保存C++对象的状态时,如何通过JNI来操作呢?

思路

当JAVA使用本地方法时,需要把该方法定义在一个类中,我们可以让该对象有一个long类型的属性,去保存本地代码C++类对象的一个地址。当我们创建C++对象后,在本地(native)方法中可以通过JNI提供的方法去获取JAVA对象,并通过JNI提供的本地方法,去给JAVA对象的属性赋值(把本地对象的指针地址赋值给JAVA对象中的属性保存)。

实现

JAVA端的代码:

public class NativeUtils {
    long mObj;

    public native int trackerInit(String path);

    public native String trackerDealFrame(String path);
}

JAVA测试代码:

public class Test{
    public static void main(String args[]){
        NativeUtils myNativeUtils=new NativeUtils();
        myNativeUtils.trackerInit(...);
        myNativeUtils.trackerDealFrame(...);
    }
}

C++代码如下:

JNIEXPORT jint JNICALL Java_com_shen_jni_NativeUtils_trackerInit
(JNIEnv *env, jobject thiz, jstring path) {
    MyTracker* myTracker = new MyTracker();
    jclass clazz = (jclass)(*env).GetObjectClass(thiz);
    jfieldID fid = (jfieldID)(*env).GetFieldID(clazz, "mObj", "J");
    (*env).SetLongField(thiz, fid, (jlong)myTracker);
    ……
}

C++代码中,参数有三个,env为JNI提供的上下文环境;thiz可以看做是调用该本地方法的JAVA对象;path是自己定义的形参。前面两个参数是JNI生成的本地方法默认添加的。

使用JAVA测试时,我们首先创建了一个包含本地方法的对象myNativeUtils,则上文所说的JNI提供的两个默认参数的第二个thiz可以当做该对象的引用。

  1. 使用jclass clazz = (jclass)(*env).GetObjectClass(thiz);获取JAVA对象。
  2. 使用jfieldID fid = (jfieldID)(*env).GetFieldID(clazz, "mObj", "J");去获取JAVA对象变量的ID。其中,“clazz”是第一步获取的对象,“mObj”是JAVA对象中保持C++对象地址的变量名,”J”是JAVA中long类型的签名。(有点像JAVA中的反射机制)
  3. 使用(*env).SetLongField(thiz, fid, (jlong)myTracker);调用JNI提供的方法去给JAVA对象的成员变量进行赋值操作,即保存了C++的指针地址。其中,“thiz”为JAVA对象的引用,”fid”为成员变量的ID,第三个参数是赋值的具体数据(这里我们使用指针的地址,并强制转换成jlong类型)。

以上我们已经将C++对象的指针地址保存在了JAVA对象的成员变量中。


下面在本地代码中,我们通过读取JAVA对象的成员变量,去恢复C++对象的引用。因为C++对象在内存已经初始化,我们只需要一个指针就可以访问该内存,并且长度还是该对象的长度,故可以恢复C++对象,继续进行调用。

jclass objClazz = (jclass)env->GetObjectClass(thiz);//obj为对应的JAVA对象
    jfieldID fid = env->GetFieldID(objClazz, "mObj", "J");
    jlong p = env->GetLongField(thiz, fid);
    MyTracker* myTracker = (MyTracker *)p;
  1. 使用jclass objClazz = (jclass)env->GetObjectClass(thiz);去获取JAVA对象。
  2. 使用jfieldID fid = env->GetFieldID(objClazz, "mObj", "J");去获取”mObj”的属性值,第一个参数是JAVA对象,第二个是相对应的long变量,第三个是long类型对应的签名。
  3. jlong p = env->GetLongField(thiz, fid);通过对象引用和成员变量ID去获取该值。
  4. MyTracker* myTracker = (MyTracker *)p;使用地址转成指针,获取到该对象的指针。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值