核心原理是 DalvikVM 由 native 启动
每个应用程序都是由一个或多个进程组成,每个进程都对应着一个 DalvikVM.DalvikVM 是由代码 native 启动,在 DalvikVM 启动后,会返回一个 JavaVM 结构体.每个线程又对应着一个 JNIEnv 的结构体.也就是说整个进程都在 native 的管理之下,所以 native 可以非常容易的改变 DalvikVM 内部的数据.但是呢,但是从 Java 层调用 native 层,还是从 native 层调用 Java 层,则得靠约定的函数形式才能进行,也就是 JNI 中的 javah 命令产生的一组映射函数.
JNI 程序开发的一般步骤:
编写带有 native 申明的 java 方法
使用 javah -jni java 类名 生成 C++ 的头文件,就是. h 文件
完成. h 文件下的所有方法
java 中 load 动态链接库文件(不要带. so 后缀)
再来看 JavaVM 与 JNIEnv 结构体的关系
在 Android 平台上,每一个 Process 只能产生一个 DalvikVM 对象,在一个 Android 的进程中,是有且只有一个虚拟器对象来服务所有的 Java 和 C/C++ 代码的.
Android 中 JNIEnv 对象和 Dalvik 的 Java VM 对象的关系如下:
一个 JNIEnv 内部包含一个 Pointer,指针指向 Dalvik 的 Java VM 对象的 FunctionTable,JNIEnv 关于程序执行环境的众多函数正是来源于 Dalvik 虚拟机;
Android 中每当一个 java 线程第一次要调用本地 C/C++ 代码时,Dalvik 虚拟机实例会为该 java 线程产生一个 JNIEnv * 指针;
java 每个线程在和 C/C++ 互相调用时,JNIEnv * 是相互独立的,互不干扰,这种做法提升了并发执行时的安全性;
当本地的 C/C++ 代码想获得当前线程所要使用的 JNIEnv 时,可以使用 Dalvik VM 对象的 JavaVMjvm->GetEnv() 方法,该方法会返回当前线程所在的 JNIEnv.
来源: http://www.jianshu.com/p/a925479b41be