JNI 理解--知识点细节讲解
 // 获取方法 IDjmethodID mid = (*env)->GetMethodID(env, cls, "sayHello", "()V");if (mid == NULL) {printf("Failed to find sayHello method\\n");return;}// 创建对象并调用方法jobject obj = (*env)->AllocObject(env, cls);(*env)->CallVoidMethod(env, obj, mid);
}

这里的 void callJavaMethod(JNIEnv *env) {} ,里面参数 *env 是什么意思 ???

在 void callJavaMethod(JNIEnv *env) 这个函数中,参数 JNIEnv *env 是 JNI(Java Native Interface)环境指针,它是 JNI 提供给本地(C/C++)代码与 Java 虚拟机(JVM)交互的主要接口。

详细解释

  • JNIEnv 是一个结构体指针,代表了当前线程与 JVM 的交互环境。
  • 通过 env,你可以调用一系列 JNI 提供的函数,比如查找 Java 类、调用 Java 方法、访问 Java 字段等。
  • 你不能自己创建或修改 JNIEnv,它由 JVM 在调用 native 方法时自动传递。

例子中的用法

在你的代码中:

void callJavaMethod(JNIEnv *env) {jclass cls = (*env)->FindClass(env, "HelloWorld");// ...
}
  • (*env)->FindClass(env, "HelloWorld") 就是通过 env 这个指针,调用 JNI 的 FindClass 方法,查找名为 HelloWorld 的 Java 类。
总结
  • JNIEnv *env 是 JNI 提供的“桥梁”,让 C/C++ 代码可以操作 Java 世界。
  • 每个本地线程都有自己的 JNIEnv 指针,不能跨线程使用。

*env 是什么意思?

*env 是一个指向 JNI 环境的指针,类型为 JNIEnv *。

它的作用是:让你的 C/C++ 代码能够调用 Java 的方法、访问 Java 的类和对象。

详细说明

  • env 是一个指针变量,类型是 JNIEnv *。
  • JNIEnv 其实是一个结构体,里面包含了很多函数指针(比如 FindClass、GetMethodID、CallVoidMethod 等)。
  • 通过 *env,你可以访问这些 JNI 提供的函数,从而操作 Java 虚拟机。

jclass cls = (*env)->FindClass(env, "HelloWorld");

这里的 (*env)->FindClass 就是通过 env 这个指针,调用 JNI 的 FindClass 方法。

总结
  • env 是 JNI 环境指针,JVM 传给你的。
  • 你用 *env 来调用 JNI 的各种函数,实现 C/C++ 和 Java 的交互。

env是不是二级指针 ???

不是,env 不是二级指针。

详细解释

  • env 的类型是 JNIEnv *,它是一级指针,指向一个 JNIEnv 结构体。
  • 你看到的 (*env)->FindClass(env, "HelloWorld") 这种写法,容易让人误以为 env 是二级指针,其实不是。
为什么这样写?
  • JNIEnv 在不同平台的实现方式不同,有时是结构体,有时是结构体指针。
  • 为了兼容性,JNI 规范推荐用 (*env)->FunctionName(env, ...) 这种写法。
  • 但本质上,env 只是一个一级指针。

JNIEnv *env; // 一级指针

总结
  • env 是一级指针(JNIEnv *),不是二级指针(JNIEnv **)。
  • 之所以用 (*env)->xxx,是因为 JNIEnv 其实是一个包含函数指针的结构体指针,这样写可以兼容所有平台。

*env 取出来的是指针,那不就是二级指针么?

你的疑问很有代表性,下面详细解释:

1. env 的类型

  • env 的类型是 JNIEnv *,也就是“指向 JNIEnv 结构体的指针”。
  • JNIEnv 结构体本身,里面存放的是一组函数指针(比如 FindClass、GetMethodID 等)。

2. (*env)->FindClass 的本质

  • (*env) 其实就是把 env 这个指针“解引用”,得到 JNIEnv 结构体本身。
  • 然后用 -> 访问结构体里的函数指针成员(比如 FindClass)。

3. 为什么不是二级指针?

  • 二级指针是 JNIEnv **,也就是“指向指针的指针”。
  • 但 env 只是 JNIEnv *,不是 JNIEnv **。
  • *env 只是把 env 这个一级指针解引用,得到结构体本身(或者结构体指针,取决于实现)。

4. 为什么要用 (*env)->xxx 这种写法?

  • 因为 JNIEnv 的定义通常是这样的(伪代码):

  typedef const struct JNINativeInterface *JNIEnv;

也就是说,env 实际上是一个指向结构体的指针,而结构体里每个成员又是一个函数指针。

  • 所以 (*env)->FindClass 就是先解引用拿到结构体,再访问结构体里的函数指针成员。

5. 总结

  • env 是一级指针(JNIEnv *),不是二级指针(JNIEnv **)。
  • *env 只是解引用,得到结构体(或结构体指针),再通过 -> 访问函数指针成员。
  • 这种写法是 JNI 的标准用法,为了兼容不同平台的实现。

可以这样理解:
  • env 是“钥匙”,*env 打开“门”,门后面有很多“按钮”(函数指针),你按下某个按钮(比如 FindClass)就能调用 JNI 的功能。