1. JNIEnv 是什么
JNIEnv 即 Java Native Interface Environment,Java 本地编程接口环境。JNIEnv 内部定义了很多函数用于简化我们的 JNI 编程。
JNI 把 Java 中的所有对象或者对象数组当作一个 C 指针传递到本地方法中,这个指针指向 JVM 中的内部数据结构(对象用jobject来表示,而对象数组用jobjectArray或者具体是基本类型数组),而内部的数据结构在内存中的存储方式是不可见的。只能从 JNIEnv 指针指向的函数表中选择合适的 JNI 函数来操作JVM 中的数据结构。
在 C 语言中,JNIEnv 是一个指向 JNINativeInterface_ 结构体的指针:
#ifdef __cplusplus
typedef JNIEnv_ JNIEnv;
#else
typedef const struct JNINativeInterface_ *JNIEnv; // C 语言
#endif
struct JNINativeInterface_ {
void *reserved0;
void *reserved1;
void *reserved2;
void *reserved3;
jint (JNICALL *GetVersion)(JNIEnv *env);
jclass (JNICALL *DefineClass)
(JNIEnv *env, const char *name, jobject loader, const jbyte *buf,
jsize len);
jstring (JNICALL *NewStringUTF)
(JNIEnv *env, const char *utf);
//省略其他函数指针
//......
}
JNINativeInterface_ 结构体中定义了非常多的函数指针,这些函数用于简化我们的 JNI 编程。C 语言中,JNIEnv 中函数的使用方式如下:
//JNIEnv * env
// env 的实际类型是 JNINativeInterface_**
(*env)->NewStringUTF(env,"Hello from JNI !");
在 C++ 代码中,JNIEnv 是一个 JNIEnv_ 结构体:
#ifdef __cplusplus
typedef JNIEnv_ JNIEnv;
#else
typedef const struct JNINativeInterface_ *JNIEnv;
#endif
struct JNIEnv_ {
const struct JNINativeInterface_ *functions;
#ifdef __cplusplus
jint GetVersion() {
return functions->GetVersion(this);
}
jclass DefineClass(const char *name, jobject loader, const jbyte *buf,
jsize len) {
return functions->DefineClass(this, name, loader, buf, len);
}
jclass FindClass(const char *name) {
return functions->FindClass(this, name);
}
jmethodID FromReflectedMethod(jobject method) {
return functions->FromReflectedMethod(this,method);
}
jfieldID FromReflectedField(jobject field) {
return functions->FromReflectedField(this,field);
}
jobject ToReflectedMethod(jclass cls, jmethodID methodID, jboolean isStatic) {
return functions->ToReflectedMethod(this, cls, methodID, isStatic);
}
jclass GetSuperclass(jclass sub) {
return functions->GetSuperclass(this, sub);
}
//省略其他函数
//......
}
JNIEnv_ 结构体中同样定义了非常多的成员函数,这些函数用于简化我们的 JNI 编程。C++ 语言中,JNIEnv 中函数的使用方式如下:
//JNIEnv * env
// env 的实际类型是 JNIEnv_*
env->NewstringUTF ( "Hello from JNI ! ");
2. 如何获取到 JNIEnv
对于单线程的情况,我们可以直接通过 JNI 方法传入的参数获取到 JNIEnv
// 第一个参数就是 JNIEnv
JNIEXPORT jstring JNICALL Java_HelloJNI_sayHello(JNIEnv *env, jobject obj)
{
return (*env)->NewStringUTF(env,"Hello from JNI !");
}
对于多线程的情况,首先我们要知道,JNIEnv 是一个线程作用域的变量,不能跨线程传递,不同线程的 JNIEnv 彼此独立。那如何在不同的线程中获取到 JNIEnv 呢:
//定义全局变量
//JavaVM 是一个结构体,用于描述 Java 虚拟机,后面会讲
JavaVM* gJavaVM;
JNIEXPORT jstring JNICALL Java_HelloJNI_sayHello(JNIEnv *env, jobject obj)
{
//线程不允许共用env环境变量,但是JavaVM指针是整个jvm共用的,所以可以通过下面的方法保存JavaVM指针,在线程中使用
env->GetJavaVM(&gJavaVM);
return (*env)->NewStringUTF(env,"Hello from JNI !");
}
//假设这是一个工具函数,可能被多个线程调用
void util_xxx()
{
JNIEnv *env;
//从全局的JavaVM中获取到环境变量
gJavaVM->AttachCurrentThread(&env,NULL);
//就可以使用 JNIEnv 了
//最后需要做清理操作
gJavaVM->DetachCurrentThread();
}
3. JNIEnv 内部函数分类
JNIEnv 中定义的函数可以分为以下几类:
函数名 | 功能 |
---|---|
FindClass | 用于获取类 |
GetObjectClass | 通过对象获取这个类 |
NewGlobalRef | 创建 obj 参数所引用对象的新全局引用 |
NewObject | 构造新 Java 对象 |
NewString | 利用 Unicode 字符数组构造新的 java.lang.String 对象 |
NewStringUTF | 利用 UTF-8 字符数组构造新的 java.lang.String 对象 |
New\Array | 创建类型为Type的数组对象 |
Get\Field | 获取类型为Type的字段 |
Set\Field | 设置类型为Type的字段的值 |
GetStatic\Field | 获取类型为Type的static的字段 |
SetStatic\Field | 设置类型为Type的static的字段的值 |
Call\Method | 调用返回类型为Type的方法 |
CallStatic\Method | 调用返回值类型为Type的static方法 |
相关的函数不止上面的这些,这些函数的介绍和使用方法,我们可以在开发过程中参考官方文档
https://docs.oracle.com/en/java/javase/11/docs/specs/jni/index.html
阅读全文
下载说明:
1、本站所有资源均从互联网上收集整理而来,仅供学习交流之用,因此不包含技术服务请大家谅解!
2、本站不提供任何实质性的付费和支付资源,所有需要积分下载的资源均为网站运营赞助费用或者线下劳务费用!
3、本站所有资源仅用于学习及研究使用,您必须在下载后的24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担!
4、本站站内提供的所有可下载资源,本站保证未做任何负面改动(不包含修复bug和完善功能等正面优化或二次开发),但本站不保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都100%无错或无bug!如有链接无法下载、失效或广告,请联系客服处理!
5、本站资源除标明原创外均来自网络整理,版权归原作者或本站特约原创作者所有,如侵犯到您的合法权益,请立即告知本站,本站将及时予与删除并致以最深的歉意!
6、如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
7、如果您喜欢该资源,请支持官方正版资源,以得到更好的正版服务!
8、请您认真阅读上述内容,注册本站用户或下载本站资源即您同意上述内容!
原文链接:https://www.dandroid.cn/archives/20396,转载请注明出处。
1、本站所有资源均从互联网上收集整理而来,仅供学习交流之用,因此不包含技术服务请大家谅解!
2、本站不提供任何实质性的付费和支付资源,所有需要积分下载的资源均为网站运营赞助费用或者线下劳务费用!
3、本站所有资源仅用于学习及研究使用,您必须在下载后的24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担!
4、本站站内提供的所有可下载资源,本站保证未做任何负面改动(不包含修复bug和完善功能等正面优化或二次开发),但本站不保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都100%无错或无bug!如有链接无法下载、失效或广告,请联系客服处理!
5、本站资源除标明原创外均来自网络整理,版权归原作者或本站特约原创作者所有,如侵犯到您的合法权益,请立即告知本站,本站将及时予与删除并致以最深的歉意!
6、如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
7、如果您喜欢该资源,请支持官方正版资源,以得到更好的正版服务!
8、请您认真阅读上述内容,注册本站用户或下载本站资源即您同意上述内容!
原文链接:https://www.dandroid.cn/archives/20396,转载请注明出处。
评论0