当前位置: 首页 > news >正文

重新认识一下JNIEnv

JNIEnv

1.JNIEnv是什么?


JNIEnv 是 Java Native Interface (JNI) 中的一个重要结构,代表 JNI 环境的指针。它提供了一组函数,用于在本地代码(C/C++)中与 Java 虚拟机(JVM)进行交互。以下是对 JNIEnv 的详细介绍:

1. 定义

  • JNIEnv 是一个指向结构体的指针,包含了 JNI 函数的指针表。通过这个指针,开发者可以调用 JNI 提供的各种功能,如创建对象、调用方法、访问字段等。

2. 作用

  • 访问 Java 对象: JNIEnv 允许本地代码访问 Java 对象的属性和方法。
  • 调用 Java 方法: 可以通过 JNIEnv 调用 Java 方法,包括静态方法和实例方法。
  • 处理异常: JNIEnv 提供了处理 Java 异常的功能,可以检查和抛出异常。

3. 使用示例

以下是一个简单的示例,展示如何使用 JNIEnv 来调用 Java 方法:

3.1 Java 代码

// Example.java
public class Example {public void greet() {System.out.println("Hello from Java!");}
}

3.2 C/C++ 代码

#include <jni.h>
#include <stdio.h>int main() {JavaVM *jvm;             // Java 虚拟机JNIEnv *env;            // JNI 环境JavaVMInitArgs vm_args; // JVM 启动参数JavaVMOption options[1]; // JVM 选项// 设置 JVM 选项,指定类路径options[0].optionString = "-Djava.class.path=."; // 当前目录vm_args.version = JNI_VERSION_1_6; // JNI 版本vm_args.nOptions = 1; // 选项数量vm_args.options = options; // 选项数组vm_args.ignoreUnrecognized = 0; // 忽略未识别的选项// 创建 Java 虚拟机jint ret = JNI_CreateJavaVM(&jvm, (void **)&env, &vm_args);if (ret != JNI_OK) {fprintf(stderr, "Failed to create JVM\\n");return 1;}// 查找 Example 类jclass cls = (*env)->FindClass(env, "Example");if (cls == NULL) {fprintf(stderr, "Failed to find Example class\\n");(*jvm)->DestroyJavaVM(jvm);return 1;}// 创建 Example 类的实例jobject obj = (*env)->AllocObject(env, cls);if (obj == NULL) {fprintf(stderr, "Failed to create Example object\\n");(*jvm)->DestroyJavaVM(jvm);return 1;}// 查找 greet 方法jmethodID mid = (*env)->GetMethodID(env, cls, "greet", "()V");if (mid == NULL) {fprintf(stderr, "Failed to find greet method\\n");(*jvm)->DestroyJavaVM(jvm);return 1;}// 调用 greet 方法(*env)->CallVoidMethod(env, obj, mid);// 销毁 Java 虚拟机(*jvm)->DestroyJavaVM(jvm);return 0;
}

4. 代码解析

  • 创建 JVM: 使用 JNI_CreateJavaVM 创建 Java 虚拟机,并获取 JNIEnv 指针。
  • 查找类和方法: 使用 FindClassGetMethodID 查找 Java 类和方法。
  • 调用方法: 使用 CallVoidMethod 调用 Java 方法。

5. 总结

JNIEnv 是 JNI 中与 Java 交互的关键结构,提供了丰富的 API 来操作 Java 对象和调用 Java 方法。通过 JNIEnv,本地代码可以方便地与 Java 进行交互,实现更复杂的功能。

(1)JNIEnv结构体介绍


JNIEnv 是 Java Native Interface (JNI) 中的一个重要结构体,它提供了本地代码与 Java 虚拟机 (JVM) 之间的接口。通过 JNIEnv,本地代码可以调用 Java 方法、访问 Java 对象的字段以及处理 Java 异常等。

1. JNIEnv 的定义

JNIEnv 是一个指向 JNI 环境的指针,通常在 JNI 函数中作为参数传递。每个线程都有自己的 JNIEnv 指针,允许线程安全地访问 JNI 函数。

2. JNIEnv 的结构

虽然 JNIEnv 的具体实现依赖于 JVM 的实现,但它通常包含一组函数指针,这些指针指向 JNI 提供的各种功能。以下是一些常用的 JNI 函数,通常在 JNIEnv 中定义:

  • 对象操作:
    • FindClass: 查找 Java 类。
    • AllocObject: 创建 Java 对象。
    • GetObjectField: 获取对象的字段值。
    • SetObjectField: 设置对象的字段值。
  • 方法调用:
    • GetMethodID: 获取方法 ID。
    • CallVoidMethod: 调用无返回值的方法。
    • CallObjectMethod: 调用返回对象的方法。
  • 异常处理:
    • ExceptionCheck: 检查是否发生异常。
    • ExceptionDescribe: 打印异常信息。
    • Throw: 抛出异常。
  • 数组操作:
    • GetIntArrayElements: 获取整型数组的元素。
    • ReleaseIntArrayElements: 释放整型数组的元素。

3. JNIEnv 的使用示例

以下是一个简单的示例,展示如何使用 JNIEnv 来调用 Java 方法:

#include <jni.h>
#include <stdio.h>void callJavaMethod(JNIEnv *env) {// 查找 Java 类jclass cls = (*env)->FindClass(env, "HelloWorld");if (cls == NULL) {printf("Failed to find HelloWorld class\\n");return;}// 获取方法 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);
}

4. 重要性

JNIEnv 是 JNI 编程的核心,提供了与 Java 交互的所有必要功能。通过 JNIEnv,本地代码可以灵活地操作 Java 对象和调用 Java 方法,从而实现 C/C++ 和 Java 之间的无缝集成。

5. 总结

JNIEnv 是一个指向 JNI 环境的指针,包含了与 Java 交互的所有函数。它在 JNI 编程中至关重要,允许本地代码访问 Java 的功能。理解 JNIEnv 的使用是成功进行 JNI 开发的关键。

(2)JNIEnv在c和c++中的区别


JNIEnv 是 Java Native Interface (JNI) 中的一个重要结构体,它提供了访问 Java 虚拟机的接口。虽然 JNIEnv 在 C 和 C++ 中的基本概念是相同的,但在使用上有一些细微的区别(重点在于参数)。以下是 JNIEnv 在 C 和 C++ 中的比较:

1. JNIEnv 的定义

  • C 语言: JNIEnv 是一个指向结构体的指针,通常在 C 代码中直接使用。
  • C++ 语言: JNIEnv 仍然是一个指向结构体的指针,但可以利用 C++ 的类和对象特性来封装 JNI 调用。

2. 使用方式

C 语言示例

在 C 语言中,使用 JNIEnv 进行 JNI 调用的方式如下:

#include <jni.h>void exampleFunction(JNIEnv *env) {jclass cls = (*env)->FindClass(env, "HelloWorld");// 其他 JNI 调用...
}

C++ 语言示例

在 C++ 中,使用 JNIEnv 的方式可以更灵活,通常会使用 C++ 的类和对象特性:

#include <jni.h>class Example {
public:void exampleFunction(JNIEnv *env) {jclass cls = env->FindClass("HelloWorld"); // 使用成员函数调用// 其他 JNI 调用...}
};

3. 方法调用

  • C 语言: 在 C 中,调用 JNI 方法时需要使用指针解引用的方式,例如 (*env)->FindClass(env, "HelloWorld")
  • C++ 语言: 在 C++ 中,可以直接使用 env->FindClass("HelloWorld"),这使得代码更简洁和易读。

4. 错误处理

在 C 语言中,错误处理通常通过返回值来实现,而在 C++ 中,可以使用异常处理机制(如果需要的话),这使得 C++ 的错误处理更加灵活。

5. 代码风格

  • C 语言: 更加注重过程式编程,代码结构相对简单。
  • C++ 语言: 支持面向对象编程,可以使用类、继承和多态等特性,使得代码更具可重用性和可维护性。

6. 总结

虽然 JNIEnv 在 C 和 C++ 中的基本功能是相同的,但在使用方式、代码风格和错误处理等方面存在一些区别。C++ 提供了更强大的语言特性,使得 JNI 的使用更加灵活和简洁。

2.JNIEnv的获取方式


JNIEnv 是 Java Native Interface (JNI) 中的一个重要结构体,它提供了访问 Java 虚拟机的接口。JNIEnv 结构体的具体实现可能会因平台和 JVM 的不同而有所不同,但它的主要作用是为本地代码提供与 Java 代码交互的功能。

1. JNIEnv 的定义

JNIEnv 是一个指向结构体的指针,包含了一系列函数指针,这些函数指针用于调用 JNI 提供的各种功能,如创建对象、调用方法、访问字段等。

2. JNIEnv 的获取方式

在 JNI 中,获取 JNIEnv 的方式主要有以下几种:

2.1 在 JNI 方法中

当你在 Java 中调用本地方法时,JVM 会自动将 JNIEnv 作为参数传递给该方法(函数静态或者动态注册,传的第一个参数)。示例:

JNIEXPORT void JNICALL Java_HelloWorld_nativeMethod(JNIEnv *env, jobject obj) {// 这里可以使用 env 进行 JNI 调用
}

2.2 在 JavaVM 中获取

如果你在非 JNI 方法(如线程创建函数)中需要获取 JNIEnv,可以通过 JavaVMGetEnv 方法获取:

JavaVM *jvm; // 假设已经创建了 JavaVM
JNIEnv *env;
jint ret = (*jvm)->GetEnv(jvm, (void**)&env, JNI_VERSION_1_6);
if (ret != JNI_OK) {// 处理错误
}

2.3 在附加线程中

如果你在一个新线程中,需要将该线程附加到 JVM,并获取 JNIEnv

JavaVM *jvm; // 假设已经创建了 JavaVM
JNIEnv *env;
jint ret = (*jvm)->AttachCurrentThread(jvm, (void**)&env, NULL);
if (ret != JNI_OK) {// 处理错误
}

3. JNIEnv 的结构体

JNIEnv 的具体实现是 JVM 相关的,通常包含以下类型的函数指针(具体实现可能会有所不同):

  • 对象创建和管理: NewObject, NewGlobalRef, DeleteGlobalRef 等。
  • 方法调用: CallVoidMethod, CallObjectMethod, CallIntMethod 等。
  • 字段访问: GetFieldID, GetObjectField, SetObjectField 等。
  • 异常处理: ExceptionCheck, ExceptionDescribe, Throw 等。

4. C 和 C++ 中的 JNIEnv 使用区别

在 C 和 C++ 中,使用 JNIEnv 的方式略有不同,主要体现在以下几个方面:

4.1 C 代码示例

JNIEXPORT void JNICALL Java_HelloWorld_nativeMethod(JNIEnv *env, jobject obj) {jclass cls = (*env)->FindClass(env, "java/lang/String");// 其他 JNI 调用
}

4.2 C++ 代码示例

在 C++ 中,通常会使用 JNIEnv 的成员函数来调用 JNI 方法,使用 -> 操作符:

JNIEXPORT void JNICALL Java_HelloWorld_nativeMethod(JNIEnv *env, jobject obj) {jclass cls = env->FindClass("java/lang/String");// 其他 JNI 调用
}

5. 总结

JNIEnv 是 JNI 中与 Java 交互的关键结构体,获取方式主要通过 JNI 方法参数、JavaVMGetEnvAttachCurrentThread 方法。在 C 和 C++ 中,使用 JNIEnv 的方式略有不同,C++ 更加面向对象,通常使用 -> 操作符来调用方法。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • RFID技术实现消防物资消防车无感化智能管理设计方案
  • ECMAScript与JavaScript的区别
  • 【leetcode】树形结构习题
  • 张雪峰分享:未来不容错过的5个证书考试
  • 直播开播极速流,如何有效接入?
  • git常用命令(patch补丁和解决冲突)
  • 什么时候分表,什么时候分库?
  • C++:opencv获取矩阵中的最大最小值--cv::minMaxLoc
  • MySQL——数据库的高级操作(二)用户管理(3)删除普通用户
  • 面试—多线程
  • 7款实用电脑办公软件和网站,工作效率飞跃提升
  • 速响低代码平台:升级营销管理系统,开启高效无忧新体验!
  • 快捷创建MySQL实例与配置数据库
  • 从数据仓库到数据中台再到数据飞轮:社交媒体的数据技术进化史
  • Oracle 数据库部署与实施
  • hexo+github搭建个人博客
  • co模块的前端实现
  • Eureka 2.0 开源流产,真的对你影响很大吗?
  • Javascript Math对象和Date对象常用方法详解
  • java多线程
  • jquery ajax学习笔记
  • leetcode378. Kth Smallest Element in a Sorted Matrix
  • leetcode98. Validate Binary Search Tree
  • ng6--错误信息小结(持续更新)
  • OSS Web直传 (文件图片)
  • Python_OOP
  • Redis学习笔记 - pipline(流水线、管道)
  • Redis在Web项目中的应用与实践
  • ubuntu 下nginx安装 并支持https协议
  • 互联网大裁员:Java程序员失工作,焉知不能进ali?
  • 基于MaxCompute打造轻盈的人人车移动端数据平台
  • 今年的LC3大会没了?
  • 聊聊directory traversal attack
  • 漫谈开发设计中的一些“原则”及“设计哲学”
  • 区块链共识机制优缺点对比都是什么
  • 王永庆:技术创新改变教育未来
  • 小程序、APP Store 需要的 SSL 证书是个什么东西?
  • 7行Python代码的人脸识别
  • C# - 为值类型重定义相等性
  • ​Benvista PhotoZoom Pro 9.0.4新功能介绍
  • ## 基础知识
  • #systemverilog# 之 event region 和 timeslot 仿真调度(十)高层次视角看仿真调度事件的发生
  • #经典论文 异质山坡的物理模型 2 有效导水率
  • (04)Hive的相关概念——order by 、sort by、distribute by 、cluster by
  • (1)常见O(n^2)排序算法解析
  • (3)(3.5) 遥测无线电区域条例
  • (6)设计一个TimeMap
  • (超详细)语音信号处理之特征提取
  • (三)elasticsearch 源码之启动流程分析
  • (三)Honghu Cloud云架构一定时调度平台
  • (转)jdk与jre的区别
  • .gitignore文件_Git:.gitignore
  • .NET 4.0中使用内存映射文件实现进程通讯
  • .Net Core 生成管理员权限的应用程序
  • .NET delegate 委托 、 Event 事件,接口回调