// 获取方法 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 的功能。