JNI 编程

来源:互联网 发布:剑三成男捏脸数据花哥 编辑:程序博客网 时间:2024/06/06 02:16

我们先引入一段程序:

Java 类,随便打印一些信息吧

package com.dk.test;public class PrintInfo {    public PrintInfo() {        //ToDo    }    public print(int num, String name, byte[] b) {        Log.i("dk", "num    : " + num);        Log.i("dk", "name   : " + name);        Log.i("dk", "size   : " + b.length);    }    private native boolean parseInfo(string infofile);    static {        System.loadLibrary("test");    }}

JNI: 演示如何在jni中正确调用java对象的方法:

JNIEXPORT jboolean JNICALL Java_com_dk_test_parseInfo(JNIENV *env, jobject obj, jstring file) {    //一定要去的全局引用,否则会被GC回收,需要记住的是JNI中传入    //的参数及返回的值都是本地引用,也就是离开了当前方法或跨线程    //时这些本地引用会失效    jobject objRef = (jobject)env->NewGlobalRef(obj);    if (objRef == NULL) {        LOGE("error: null pointer exception");        return false;    }    //通过全局引用取得对象的类    jclass objClass = env->GetObjectClass(objRef);    //获取对象的方法    //objclass: 定义了该方法的类    //"print" : 需要在c/c++中调用的方法名    //"(ILjava/lang/String;[B)Z": 方法标签,用来描述方法,不    //   用死记对应关系,只需要找到类对应的class文件执行:    //     javap -s 类名    //   即可生成所有该类中方法的描述    //   androidstudio class 在    //   app/build/intermediates/classes/debug/com/..下面    jmethodId printFuncId = env->GetMethodId(objClass, "print", "(ILjava/lang/String;[B)Z");    jint num = 30;    //但凡jobject的子类jstring,jclass,jarray使用时一定要使    //用全局应用,否则会报控制异常    jstring name = (jstring)env->NewGlobalRef(env->NewStringUTF("dkos"));    //jarray 引用    jbyteArray b = (jbyteArray)env->NewGlobalRef(env->NewByteArray(10));    unsigned char *mail = "dk_mcu@126.com";    jbyte* bcontent = (jbyte*)(mail)    //byte数组的赋值方法    env->SetByteArrayRegion(b, 0, strlen(mail), bcontent);    //调用java类的方法    env->CallBooleanMethod(objRef, printFuncId, num, name, b);    //回收全局引用    env->DeleteGlobalRef(name)    env->DeleteGlobalRef(b);    env->DeleteGlobalRef(objRef);    //jni方法返回    return true;}

需要注意:假设上面调用java方法,或引用jobject对象,或是传递参数给java方法时,jobject对象若不全局引用常见的错误为:

E/dalvikvm( 5302): JNI ERROR (app bug): accessed stale local reference 0x40839e59

总结:

>

1 jni接口中使用java传递的参数或是传递参数,返回参数给java时一定使用全局引用,否则会被GC回收导致程序crash,报空指针异常等错误

2.使用引用时,env->NewGlobalRef(ref) 和env->DeleteGlobalRef(ref)成对使用,防止过多占用内存,因为全局引用GC时不会回收的

3.上面所讲都是针对android ics之后的版本,至于以前的不需要这么做

0 0
原创粉丝点击