IE盒子

搜索
查看: 129|回复: 1

Java Native Interface使用指南(持续更新)

[复制链接]

3

主题

13

帖子

23

积分

新手上路

Rank: 1

积分
23
发表于 2023-1-7 21:54:34 | 显示全部楼层 |阅读模式
Java Native Interface使用指南(持续更新)
0.前言
鉴于我们经常需要使用java的本地方法调用C/C++进行编写程序,但是经常不知道如何在C++侧解析来自java的变量和构造java需要的变量作为返回,不知道如何释放jni对象以至于造成内存泄漏。这里对java的本地方法做一个总结,方便自己进行查阅,加快编码速度。
1.Java Native Interface官网
https://docs.oracle.com/javase/8/docs/technotes/guides/jni/

官网第一章镇楼,未尽处请参阅官网爸爸。
2.变量类型对应关系
2.1 基本数据类型



2.2 引用数据类型




2.3 变量类型签名关系


比如:


后续看是否有必要在这里补充各种数据类型的签名写法
(1)基本数据类型上面已经有了
(2)数组是中括号:[
(3)函数入参类型使用小括号包围
(4)引用类型使用L+包名路径(其中.替换为/)
3.各种java类型和C++类型的相互转换示例代码
3.1 String用法
解析:
const char *stringPtr = env->GetStringUTFChars(jString, nullptr);
std::string cppString(stringPtr);
释放:
env->ReleaseStringUTFChars(jString, stringPtr);
env->DeleteLocalRef(jString);

4.Android JNI注意的地方
5.一些小知识
5.1 可以删除空引用,放心删除引用,不必要事先进行判空
对于这样是没必要的:
if (object != nullptr) {
    env->DeleteLocalRef(object);
}
直接:
env->DeleteLocalRef(object);

5.2 实现非JNI函数处理java数据,通过JavaVM获取JNIEnv(无中生有?)
5.2.1初始化JavaVM
JavaVM *g_javaVm = nullptr; // 理论上,每个进程可以有多个 JavaVM,但 Android 只允许有一个。

// 初始化时操作, 通过初始的JNIEnv获取全局的JavaVM
// 线程不允许共用env环境变量,但是JavaVM指针是整个jvm共用的,所以可以通过下面的方法保存JavaVM指针,在线程中使用
int ret = env->GetJavaVM(&g_javaVm);
if (ret != JNI_OK || g_javaVm == nullptr) {
    printf("env->GetJavaVM(&g_javaVm) error code(%d) or g_javaVm(%p) == nullptr!!!", ret, g_javaVm);
    return JNI_ERR;
}5.2.2使用JavaVM在任意线程中获取JNIEnv
// 从全局的JavaVM中获取到环境变量
JNIEnv* env = nullptr;
g_javaVm->AttachCurrentThread(&env, nullptr);
if (env == nullptr) {
    g_javaVm->DetachCurrentThread();
    printf("env == nullptr");
}
g_javaVm->DetachCurrentThread();5.2.3删除全局JavaVM
if (g_javaVm != nullptr) {
    printf("clean g_javaVm!");
    g_javaVm = nullptr;
}5.3 全局引用的使用
5.3.1初始化全局引用,各个线程都可使用
jobject g_javaObject = nullptr;

// jobject变量也不允许在线程中共用,因此需要创建全局的jobject对象在线程中访问该对象
g_javaObject = env->NewGlobalRef(object);
if (g_javaObject == nullptr) {
    printf("env->NewGlobalRef(object) error!!!");
    return JNI_ERR;
}5.3.2使用全局引用
// 使用
env->CallIntMethod(g_javaObject , methodId, var1, var2);5.3.3删除全局引用
if (g_javaObject != nullptr) {
    printf("clean g_object!");
    env->DeleteGlobalRef(g_javaObject);
    g_javaObject = nullptr;
}
回复

使用道具 举报

5

主题

9

帖子

20

积分

新手上路

Rank: 1

积分
20
发表于 2025-5-19 05:47:18 | 显示全部楼层
撸过
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表