JNI-JNIEnv和JavaVM

JNIEnv

  • 表示Java调用Native语言的环境,是一个封装了几乎全部JNI方法的指针
  • 只在创建它的线程生效,不能跨线程传递
  • 不同线程的JNIEnv彼此独立
  • Native环境中创建的线程,如果需要访问JNI,必须要调用AttachCurrentThread关联,并使用DetachCurrentThread解除链接

JavaVM

  • JavaVM是虚拟机在JNI层的代表
  • 一个进程只有一个JavaVM,所有线程共用一个JavaVM
  • 在Java里,每个进程可以产生多个JavaVM对象
  • 但是在Android上,每个进程只有一个Dalvik虚拟机对象来服务所有Java和C/C++代码

Java的dex字节码和C/C++的.so同事运行Dalvik虚拟机之内,共同使用一个进程空间。之所有能相互调用,也是因为有Dalvik虚拟机。
当Java代码需要C/C++代码时,在Dalvik虚拟机加载进
.so库时,会先调用JNI_Onload(),此时会把JavaVM对象的指针存储在C层Jni组件的全局环境中。
在Java层调用C层的本地函数时,调用C本地函数的线程必然通过Dalvik虚拟机来调用C层的本地函数,此时,Dalvik虚拟机会为本地的C组件实例化一个JNIEnv指针,该指针指向Dalvik的具体函数列表,当JNI的C组件调用Java层的方法或者属性时,需要通过JNIEnv指针来进行调用。当本地C/C++想获得当前线程所要使用的JNIEnv时,可以使用Dalvik虚拟机对象的JavaVM* jvm->GetEnv()返回当前线程所在的JNIEnv*。

你可能感兴趣的:(JNI-JNIEnv和JavaVM)