关于android的JNI几点注意问题。

来源:互联网 发布:c语言中数组的定义 编辑:程序博客网 时间:2024/05/21 14:52

1.注册函数映射表

      JNI API为了避免丑陋的函数名,提供了方法向Java虚拟机注册函数映射表。

      这样当Java调用Native接口的时候,Java虚拟机就可以不用根据函数名来决定调用哪个函数了,直接通过查询表格就可以找到需要调用的函数了。

2.关于JNI中的引用

     JNI支持三种引用:局部引用、全局引用、弱全局引用。

     局部引用和全局引用有不同的生命周期:

     当本地方法返回时,局部引用会被自动释放。而全局引用和弱引用必须手动释放。

     局部引用或者全局引用会阻止GC回收它们所引用的对象,而弱引用则不会。

     不是所有的引用可以被用在所有的场合。

     例如,一个本地方法创建一个局部引用并返回后,再对这个局部引用进行访问是非法的。

2.1. 局部引用:

      局部引用只有在创建它的本地方法返回前有效。本地方法返回后,局部引用会被自动释放。(static局部对象也是一样)

      实际上JNI中的局部引用和C语言中局部变量是不同的,他的有效期是当前Native函数被调用的上下文中。

      我理解的调用上下文,为Java虚拟机的调用流程。Native函数是被Java虚拟机调用的,Native函数执行完成之后,控制流程将继续返回给Java虚拟机。

      局部变量在Native函数中,由Native代码调用Java虚拟机的JNI接口创建,秉着谁创建谁销毁的原则,当Native函数执行完成之后,如果局部引用没有被Native代码显示删除,那么局部引用在Java虚拟机中还是有效的。

      Java虚拟机来决定在什么时候来删除这个对象。这和C语言的局部变量概念是不同的。这也可以解释为什么Natvie函数能够以一个局部引用为返回值了。

      局部引用在Native代码显示释放非常重要。

      (如果你实现的Native函数是工具函数,会被频繁的调用。如果你在Native函数中没有显示删除局部引用,那么每次调用该函数Java虚拟机都会创建一个新的局部引用,造成局部引用过多。尤其是该函数在Native代码中被频繁调用,代码的控制权没有交还给Java虚拟机,所以Java虚拟机根本没有机会释放这些局部变量。)

       JNIapi中有三个函数对局部引用进行处理:EnsureLocalCapacity、PushLocalFrame、PopLocalFrame

       可以用栈来理解局部变量。

2.2. 全局引用:

      全局引用可以跨方法、跨线程使用,直到它被手动释放才会失效。

      同局部引用一样,全局引用也会阻止它所引用的对象被GC回收。NewGlobalRef和DeleteGlobalRef.  

2.3. 弱引用

      弱引用使用NewGlobalWeakRef创建,使用DeleteGlobalWeakRef释放。

      与全局引用类似,弱引用可以跨方法、线程使用。

      与全局引用不同的是,弱引用不会阻止GC回收它所指向的VM内部的对象。

      NewWeakGlobalRef和DeleteWeakGlobalRef。使用的时候应该检查它的有效性

      每一个JNI引用被建立时,除了它所指向的JVM中的对象以外,引用本身也会消耗掉一个数量的内存。

      作为一个JNI程序员,应该对程序在一个给定时间段内使用的引用数量十分小心。

      短时间内创建大量不会被立即回收的引用会导致内存溢出。


以上,是整理的部分关于JNI的知识。




0 0
原创粉丝点击