600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > 09-JavaVM与JNIEnv

09-JavaVM与JNIEnv

时间:2023-05-15 18:53:17

相关推荐

09-JavaVM与JNIEnv

JavaVM与JNIEnv

JNI中其他类型:成员域ID和方法ID

//成员域ID、成员方法ID:struct _jfieldID;typedef struct _jfieldID* jfield;struct _jmethodID;typedef _jmethodID* jemthodID

jvalue : 可以代表不同类型的变量,注意jboolean和jlong

typedef union jvalue {jboolean z;jbyte b;jchar c;jshorts;jint i;jlong j;jfloatf;jdoubled;jobjectl;} jvalue;

JNI_Onload

JNI_Onload是有共享库导出的,有用户来实现。

执行时机:在一个so被加载时调用

/* Prototypes for functions exported by loadable shared libs. These are called by JNI, not provided by JNI. */JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved);//第二个参数是保留的JNIEXPORT void JNI_OnUnload(JavaVM* vm, void* reserved);

JavaVM和JNIEnv

struct _JNIEnv;struct _JavaVM;typedef const struct JNINativeInterface* C_JNIEnv;#if defined(__cplusplus)typedef _JNIEnv JNIEnv;typedef _JavaVM JavaVM;#elsetypedef const struct JNINativeInterface* JNIEnv;typedef const struct JNIInvokeInterface* JavaVM;#endif

jnienv在C和cpp中的使用:使用C很繁琐,用CPP比较简洁

// C中jclass TestJclass = (*env)->FindClass(env,"com/showme/reflectiontest/Test");jfieldID publicStaticField_jfieldID = (*env)->GetStaticFieldID(env,TestJclass, "publicStaticField","Ljava/lang/String;");jstring publicStaticField_content = (jstring) (*env)->GetStaticObjectField(env,TestJclass,publicStaticField_jfieldID);const char *content_ptr = (*env)->GetStringUTFChars(env,publicStaticField_content, NULL);__android_log_print(4, "showme->jni", "jni->%s", content_ptr);// cpp中jclass TestJclass = env->FindClass("com/showme/reflectiontest/Test");jfieldID publicStaticField_jfieldID = env->GetStaticFieldID(TestJclass, "publicStaticField","Ljava/lang/String;");jstring publicStaticField_content = (jstring) env->GetStaticObjectField(TestJclass,publicStaticField_jfieldID);const char *content_ptr = env->GetStringUTFChars(publicStaticField_content, nullptr);__android_log_print(4, "showme->jni", "jni->%s", content_ptr);

JavaVM

JavaVM是虚拟机在JNI层的代表,一个进程只有一个JavaVM,所有的线程共用一个JavaVM

JNIInvokeInterface_结构封装和JVM相关的功能函数,如销毁JVM,获得当前线程Java执行环境在C和C++中JavaVM的定义有所不同,在C中JavaVM是JNIInvokeInterface_类型指针,而在C++中又对JNIInvokeInterface_进行了一次封装推荐用C++来编写JNI代码,比C中少了一个参数

JNIEnv

JNIEnv表示Java调用native语言的环境,是一个封装了大量JNI方法的指针

JNIENv只在创建它的线程中生效,不能跨线程传递,不同线程的JNIENv彼此独立

native环境中创建的线程,如果需要访问JNI,必须要调用AttachCurrentThread关联,并使用DetachCurrentThread解除链接

JavaVM的获取

1、在JNI_Onload中作为参数获得,如下:

JNIEXPORT jint JNICALL JNI_Onload(JavaVM* vm,void* reserved),该函数由ART负责自动化查找和传入参数进行调用

2、通过JNIEnv的GetJavaVM函数获取,如下:

JavaVM* thisvjm = nullptr;

env->GetJavaVM(&thisjvm);

native创建的新线程,需要在线程中使用线程自身的JNIEnv

// c创建新线程pthread_t thread;pthread_create(&thread, nullptr, threadtest, nullptr);pthread_join(thread, nullptr);// 新线程,需要获取自身的JNIEnv,并附加到JavaVM(这个JNIEnv需要知道自身从属于哪个虚拟机)void *threadtest(void *args) {JNIEnv *threadenv = nullptr;if (globalVM->GetEnv((void **) &threadenv, JNI_VERSION_1_6) == JNI_OK);int result = globalVM->AttachCurrentThread(&threadenv, nullptr);//重要if (result == JNI_OK);threadenv->ExceptionDescribe();//打印异常threadenv->ExceptionClear();//清除异常globalVM->DetachCurrentThread();//重要pthread_exit(0);}

注意事项-这个真的很重要

JNIEnv是与一个ClassLoader绑定的,当使用env->FindClass()进行类的查询和加载时便是使用的这个ClassLoader(在主线程中可以)JNIEnv是当前Java线程的执行环境,一个JVM对应一个JavaVM结构,而一个JVM中可能创建多个Java线程,使用pthread_create新建的线程当使用AttachCurrentThread(&env,NULL)获取到JNIEnv后,该JNIEnv的ClassLoader并不是主线程的ClassLoader,因此也就无法加载app自己的Class (解决方式是:1、主线程在启动子线程时,将ClassLoader当做参数传递,2、在主线程中创建全局的ClassLoader)

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。
扩展阅读