【混合编程jni 】第九篇之Jni总结

举报
香菜聊游戏 发表于 2022/06/26 21:32:40 2022/06/26
【摘要】 动态库的加载可以使用标准 System.loadLibrary 从共享库加载原生代码。关于参数传递 int、char 等这样的基本数据类型,在本地代码和JVM之间进行复制传递,而对象是引用传递的。每一个引用都包含一个指向JVM中相应的对象的指针,但本地代码不能直接使用这个指针,必须通过引用来间接使用。局部引用和全局引用传递给原生方法的每个参数,以及 JNI 函数返回的几乎每个对象都属于“局部...

动态库的加载

可以使用标准 System.loadLibrary 从共享库加载原生代码。

关于参数传递 int、char 等这样的基本数据类型,在本地代码和JVM之间进行复制传递,

而对象是引用传递的。每一个引用都包含一个指向JVM中相应的对象的指针,

但本地代码不能直接使用这个指针,必须通过引用来间接使用。

局部引用和全局引用

传递给原生方法的每个参数,以及 JNI 函数返回的几乎每个对象都属于“局部引用”。

这意味着,局部引用在当前线程中的当前原生方法运行期间有效。

在原生方法返回后,即使对象本身继续存在,该引用也无效。

这适用于 jobject 的所有子类,包括 jclass、jstring 和 jarray。(启用扩展的 JNI 检查时,运行时会针对大部分引用误用问题向您发出警告。)

获取非局部引用的唯一方法是通过 NewGlobalRef 和 NewWeakGlobalRef 函数。

如果您希望长时间保留某个引用,则必须使用“全局”引用。

NewGlobalRef 函数将局部引用作为参数,然后返回全局引用。

在调用 DeleteGlobalRef 之前,全局引用保证有效。

一个对象从JVM传递给本地方法时,就把控制权移交了过去,

JVM会为每一个对象的传递创建一条记录,一条记录就是一个本地代码中的引用和JVM中的对象的一个映射。

记录中的对象不会被GC回收。所有传递到本地代码中的对象和从JNI函数返回的对象都被自动地添加到映射表中。

当本地方法返回时,VM会删除这些映射,允许GC回收记录中的数据。

JavaVM 和 JNIEnv

两者本质上都是指向函数表的二级指针。

(在 C++ 版本中,它们是一些类,这些类具有指向函数表的指针,并具有每个通过该函数表间接调用的 JNI 函数的成员函数。)

JavaVM 提供“调用接口”函数,您可以利用此类来函数创建和销毁 JavaVM。理论上,每个进程可以有多个 JavaVM

JNIEnv 提供了大部分 JNI 函数。您的原生函数都会收到 JNIEnv 作为第一个参数。

JNIEnv 将用于线程本地存储。因此无法在线程之间共享 JNIEnv。

如果一段代码无法通过其他方法获取自己的 JNIEnv,您应该共享相应 JavaVM,然后使用 GetEnv 发现线程的 JNIEnv。

jclass、jmethodID 和 jfieldID

如果要通过原生代码访问对象的字段,可以按下面的顺序操作:

使用 FindClass 获取类的类对象引用 使用 GetFieldID 获取字段的字段 ID 使用适当函数获取字段的内容,例如 GetIntField 同样,如需调用方法,

首先要获取类对象引用,

然后获取方法 ID。方法 ID 通常只是指向内部运行时数据结构的指针。

建议查找一次这些值并将结果缓存在原生代码中。由于每个进程只能包含一个 JavaVM,因此将这些数据存储在静态本地结构中是一种合理的做法。

线程

线程通常从受管理代码启动(使用 Thread.start()),但也可以在其他位置创建,然后附加到 JavaVM。

例如,可以使用 AttachCurrentThread() 或 AttachCurrentThreadAsDaemon() 函数附加通过 pthread_create() 或 std::thread 启动的线程。在附加之前,线程不包含任何 JNIEnv,也无法调用 JNI。

通常,最好使用 Thread.start() 创建需要调用 Java 代码的任何线程。这样做可以确保您有足够的堆栈空间、属于正确的 ThreadGroup 且与您的 Java 代码使用相同的 ClassLoader。而且,设置线程名称以在 Java 中进行调试也比通过原生代码更容易

附加原生创建的线程会构建 java.lang.Thread 对象并将其添加到“主”ThreadGroup,从而使调试程序能够看到它。在已附加的线程上调用 AttachCurrentThread() 属于空操作。

通过 JNI 附加的线程在退出之前必须调用 DetachCurrentThread()。

总结:

这是最后一篇jni的了,下面将介绍其他的框架,减少jni的开发难度和复杂的


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。