写点什么

JNI 提示

用户头像
Changing Lin
关注
发布于: 9 小时前
JNI 提示

1.常规提示

尽量减少 JNI 层的占用空间。

  • 尽可能减少跨 JNI 层编组资源的次数

  • 尽可能避免在使用受管理编程语言编写的代码与使用 C++ 编写的代码之间进行异步通信

  • 尽可能减少需要接触 JNI 或被 JNI 接触的线程数

  • 将接口代码保存在少量易于识别的 C++ 和 Java 源位置,以便将来进行重构

受管理代码:使用 Java 或 Kotlin 编程语言编写

原生代码:使用 C/C++ 编写

2.JavaVM 和 JNIEnv

JNI 定义了两个关键数据结构,两者本质上都是指向函数表的二级指针

JavaVM 提供“调用接口”函数,您可以利用此类来函数创建和销毁 JavaVM

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

3.线程

最好使用 Thread.start() 创建需要调用 Java 代码的任何线程

这样做可以确保您有足够的堆栈空间、属于正确的 ThreadGroup 且与您的 Java 代码使用相同的 ClassLoader

4.jclass、jmethodID 和 jfieldID

原生代码访问对象的字段的步骤:

  • 使用 FindClass 获取类的类对象引用

  • 使用 GetFieldID 获取字段的字段 ID

  • 使用适当函数获取字段的内容,例如 GetIntField

JNIEXPORT void JNICALLJava_com_example_hellojnicallback_MainActivity_test(JNIEnv *env, jobject thiz) {
jclass clz = (*env)->FindClass(env, "com/example/hellojnicallback/MainActivity"); jfieldID jfieldId = (*env)->GetFieldID(env, clz, "minute", "I"); jint value = (*env)->GetIntField(env, thiz, jfieldId);
LOGI("这里是我自己编写的测试方法: %d %d %d", env, thiz, value);}
复制代码

原生代码访问对象的方法的步骤:

  • 使用 FindClass 获取类的类对象引用

  • 使用 GetMethodID 获取对象的方法 ID

  • 使用适当函数调用方法,例如 CallLongMethod

jclass 是类引用,必须通过调用 NewGlobalRef 来保护它

5.局部引用和全局引用

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

局部引用在当前线程中的当前原生方法运行期间有效

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


6.UTF-8 和 UTF-16 字符串

Java 编程语言使用的是 UTF-16

  • 不要忘记 Release 您 Get 的字符串

  • 传递给 NewStringUTF 的数据必须采用修改后的 UTF-8 格式

7.原始数组

JNI 提供访问数组对象内容的函数

8.区域调用

// 写法1jbyte* data = env->GetByteArrayElements(array, NULL);if (data != NULL) {		memcpy(buffer, data, len);		env->ReleaseByteArrayElements(array, data, JNI_ABORT);}
// 写法2env->GetByteArrayRegion(array, 0, len, buffer);
复制代码

第二种写法具有诸多优势:

  • 需要一个 JNI 调用而不是两个,从而减少开销。

  • 不需要固定或额外复制数据。

  • 降低程序员出错风险,因为不存在操作失败后忘记调用 Release 的风险。

9.异常

  • 在异常挂起时,不得调用大多数 JNI 函数

10.扩展的检查

Android 还提供了一种名为 CheckJNI 的模式,其中 JavaVM 和 JNIEnv 函数表指针已切换为在调用标准实现之前执行一系列扩展的检查的函数表。

11.原生库

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

12.64 位注意事项

为了支持使用 64 位指针的架构,在 Java 字段中存储指向原生结构的指针时,请使用 long 字段而不是 int

13.不支持的功能/向后兼容性

14.常见问题解答:为什么我会收到 UnsatisfiedLinkError?

15.常见问题解答:为什么 FindClass 找不到我的类?

16.常见问题解答:如何使用原生代码共享原始数据?

发布于: 9 小时前阅读数: 3
用户头像

Changing Lin

关注

获得机遇的手段远超于固有常规之上~ 2020.04.29 加入

我能做的,就是调整好自己的精神状态,以最佳的面貌去面对那些未曾经历过得事情,对生活充满热情和希望。

评论

发布
暂无评论
JNI 提示