zoukankan      html  css  js  c++  java
  • jni 基础

    1.
    java层对应到JNI层
    除了 基本类型,基本类型数组,string,throwable,class 之外,都是用jobject来代替

    2.
    JNIEnv是native层,一个线程作用域的,调用虚拟机方法的对象
    一个线程只能用自己的JNIEnv对象(类似Threadlocal的作用于效果,和线程对象相关),如果没有
    那么通过JavaVM的AttachCurrentThread 获得当前线程的JNIEnv
    当当前线程结束时,调用JavaVM->DetachCurrentThread 释放对应的资源

    3.
    使用java对象,首先要定位到对象的jfieldID 或 jmethodID
    这样可以读写/访问 对象的成员变量或成员函数

    一般先用FindClass找到jclass
    然后用GetMethodID(jclass,methodName,methodSig)得到jmethodID
    然后用env->CallXXXXMethod(jobject,jmethodID,params...)
    XXXX为返回值类型的名称

    成员变量访问是类似的
    SetXXXXField
    GetXXXXField

    XXXX是成员变量类型名称
    如Object,Byte,Int。。。。


    4.
    jstring

    env->
    NewString new一个jstring对象(存储Unicode)
    NewStringUTF new一个jstring对象(存储Unicode,并用UTF-8编码)

    const jchar* GetStringChars(jstring string, jboolean* isCopy)
    const char* GetStringUTFChars(jstring string, jboolean* isCopy) 得到一个 UTF编码的jstring的 char数组

    typedef uint16_t jchar; /* unsigned 16 bits */

    当在Native层通过GetStringXXXChars获取到了char* ,并使用完成后,需要手动调用ReleaseStringChars() 或 ReleaseStringUTFChars()
    释放jstring对象,否则可能造成在native层导致JVM产生内存泄露


    5.
    函数签名
    签名格式,和类型映射名称
    格式:(参数类型1;参数类型2;参数类型3;。。。。;)返回值类型

    类型:
    基本类型,对象,int数组,对象数组
    这4类

    基本类型: 有一对一的类型名称映射
    对象为: L/对象包名/对象名;
    int数组为: [I
    对象数组为: [L/对象包名/对象名;

    例如 int add(float, float) 的签名为
    (F;F;)I


    =====

    垃圾回收

    java层传递的一些对象,如 thiz 可能在运行中会被垃圾回收。
    所以如果需要在native层保存这个引用,需要小心在下次使用的时候,判断一下是否被回收了
    native层的引用,不像java层,被虚拟机管理了强引用等方式来进行垃圾回收,也就是说
    这里引用了一个地址,jvm并不知道

    那么jni有3种为我们提供的引用策略,我们产生了一个引用,并且根据引用方式不同,jvm对这些引用的回收策略也不同

    1.LocalRefernce 本地引用。作为函数参数传递进来,离开native函数后,这些参数可能被回收
    2.GlobalRefrence 全局引用。如果不主动释放,就不会被垃圾回收。(类似java层,从GCRoot可达的强引用)
    3.WeakGlobalRefrence 全局弱音引用。在jvm运行过程种可能会被回收,调用前用JNIEnv的IsSameObject 判断某个引用是否被回收了(和java层的WeakRefrece有些类似)


    2.GlobalRefrence:
    如果需要将一个LocalRefernce转为GlobalRefrence
    env->NewGlobalRef(ref)

    往往在native对象的构造函数中这样使用
    然后在析构函数中用
    env->DeleteGolbalRef(ref) 解除引用

    1.LocalRefernce:
    虽然可以等函数调用完后,会自动回收java对象,但是也可以手动立即回收
    调用
    env->DeleteLocalRef(jref)
    原因是,如果在这个函数里new了太多临时的java对象,而不即时手动清除,可能在函数执行过程中会产生内存溢出

    ====

    JNI中的异常

    在jni中如果调用某个jnienv的函数产生了异常,
    那么不会立刻中断本地函数的执行,
    要等到当前函数执行完后,返回到java层后,才会抛出异常
    如果在native层产生了不可恢复的异常(业务逻辑层面上的)
    那么需要做一些手动的资源清除,如释放全局变量,然后等
    回到java层再catch异常

    jni层可以获取,修改产生的异常
    ExceptionOccured 是否有异常发生
    ExceptionClear 清理掉发生的异常信息
    ThrowNew 向java层抛出异常

    ====

  • 相关阅读:
    Oracle.EntityFrameworkCore使用时报错:Specified cast is not valid
    .net core webapi通过中间件获取请求和响应内容
    金额数字语音播报
    FluentData微型ORM
    记阿里巴巴数据采集
    给定一个N阶矩阵A,输出A的M次幂(M是非负整数)(Java)
    求出区间[a,b]中所有整数的质因数分解。(Java)(转载)
    最大公约数 最小公倍数(Java)
    十六进制转八进制(Java)
    杨辉三角形(java)
  • 原文地址:https://www.cnblogs.com/cyy12/p/12154326.html
Copyright © 2011-2022 走看看