欢迎访问昆山宝鼎软件有限公司网站! 设为首页 | 网站地图 | XML | RSS订阅 | 宝鼎邮箱 | 后台管理


新闻资讯

MENU

软件开发知识
原文出处: Young_Blog

数组的操纵

数组是一个很常用的数据范例,在可是在 JNI 中并不能直接操纵 jni 数组(好比 jshortArray、jfloatArray)。利用要领是:

  1. 获取数组长度:jsize GetArrayLength(jarray array)
  2. 建设新数组: ArrayType New<PrimitiveType>Array(jsize length);
  3. 通过JNI数组获取一个C/C++数组:<type>* Get<type>ArrayElements(jshortArray array, jboolean *isCopy)
  4. 指定原数组的范畴获取一个C/C++数组(该要领只针对付原始数据数组,不包罗Object数组):void Get<PrimitiveType>ArrayRegion(JNIEnv *env, ArrayType array, jsize start, jsize len, NativeType *buf);
  5. 配置数组元素:void Set<type>ArrayRegion(jshortArray array, jsize start, jsize len,const <type> *buf)。again,假如是Object数组需要利用void SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject value);
  6. 利用完之后,释放数组:void Release<type>ArrayElements(jshortArray array, jshort *elems, jint mode)

有点要说明的:

1、上面的3中的 isCopy:当你挪用 getArrayElements 时 JVM(Runtime)可以直接返回数组的原始指针,可能是 copy 一份,返回给你,这是由 JVM 抉择的。所以 isCopy 就是用来记录这个的。他的值是 JNI_TURE 可能 JNI_FALSE

2、6释放数组。必然要释放你所得到数组。个中有一个mode参数,其有三个可选值,别离暗示:

  • 0
  • 原始数组:答允原数组被垃圾接纳。
  • copy: 数据会从get返回的buffer copy归去,同时buffer也会被释放。
  • JNI_COMMIT
  • 原始数组:什么也不做
  • copy: 数据会从get返回的buffer copy归去,同时buffer不会被释放。
  • JNI_ABORT
  • 原始数组:答允原数组被垃圾接纳。之前由JNI_COMMIT提交的对数组的修改将得以保存。
  • copy: buffer会被释放,同时buffer中的修改将不会copy回数组!
  • 关于引用与垃圾接纳

    好比上面有个要领传了一个 jobject 进来,然后我把她生存下来,利便今后利用。这样做是不可哒!因为他是一个 LocalReference,所以不能担保 jobject 指向的真正的实例不被接纳。也就是说有大概你用的时候谁人指针已经是个野指针的。然后你的措施就直接 Segment Fault 了,呵呵。

    在JNI中提供了三种范例的引用:

    1. Local Reference:即当地引用。在JNI层的函数,所有非全局引用工具都是Local Reference, 它包罗函数挪用是传入的jobject和JNI成函数建设的jobject。Local Reference的特点是一旦JNI层的函数返回,这些jobject就大概被垃圾接纳。
    2. Glocal Reference:全局引用,这些工具不会主动释放,永远不会被垃圾接纳。
    3. Weak Glocal Reference:弱全局引用,一种非凡的Global Reference,在运行进程中有大概被垃圾接纳。所以利用之前需要利用jboolean IsSameObject(jobject obj1, jobject obj2)判定它是否已被接纳。

    Glocal Reference:
    1. 建设:jobject NewGlobalRef(jobject lobj);
    2. 释放:void DeleteGlobalRef(jobject gref);

    Local Reference:
    LocalReference也有一个释放的函数:void DeleteLocalRef(jobject obj),他会当即释放Local Reference。 这个要领大概略显多余,其实也是有它的用处的。适才说Local Reference会再函数返回后释放掉,可是如果函数返回前就有许多引用占了许多内存,最好函数内就尽早释放不须要的内存。

    关于JNI_OnLoad

    开头提到 JNI_OnLoad 是 Java1.2 中新增加的要领,对应的尚有一个 JNI_OnUnload,别离是动态库被 JVM 加载、卸载的时候挪用的函数。有点雷同于 Windows 里的 DllMain。
    前面提到的实现对应 native 的要领是实现 javah 生成的头文件中界说的要领,这样有几个漏洞:

    1. 函数名太长。很长,相当长。
    2. 函数会被导出,也就谁说可以在动态库的导出函数表内里找到这些函数。这将有利于别人对动态库的逆向工程,因此带来安详问题。

    此刻有了JNI_OnLoad,环境许多几何了。你不仅能在个中完成动态注册 native 函数的事情还可以完成一些初始化事情。Java 对应的有了 jint RegisterNatives(jclass clazz, const JNINativeMethod *methods,jint nMethods)函数。参数别离是:

  • jclass clazz,于native层对应的java class
  • const JNINativeMethod *methods这是一个数组,数组的元素是JNI界说的一个布局体JNINativeMethod
  • 上面的数组的长度
  • JNINativeMethod:代码中的界说如下

    /*
     * used in RegisterNatives to describe native method name, signature,
     * and function pointer.
     */
    
    typedef struct {
        char *name;
        char *signature;
        void *fnPtr;
    } JNINativeMethod;

    所以他有三个字段,昆山软件开发,别离是

    用 id 把 Java 中的工具  <a href=苏州软件定制开拓 和 native 中的工具绑定起来" class="aligncenter size-full wp-image-30099" title="Snipaste_2018-10-08_08-16-09" src="/uploads/allimg/c181009/153Z2Z4BO50-11054.png" />