1, 基本概念
1,JNI 是什么?
2,JNI 有和作用?
3,JNI 为什么存在?
JNI(Java Native Interface): java 本地接口。Natvie 一般指 C/C++。
可以这么说,JNI是 java 和 C/C++ 之间的桥梁,通过JNI技术, java 和 C/C++ 可以互相调用。
首先,Java是平台无关的,但是承载java的虚拟机是用C/C++写的,但是虚拟机是运行在具体的平台上,是平台相关的。然而,使用JNI技术就可以屏蔽不同操作系统平台之间的差异。其次,C/C++在java之前就广泛使用了,JNI技术避免了java重复写功能写代码的窘况。最后, C/C++相对于java在一些场合更加有效率,所以JNI技术也是不可或缺的。
虚拟机特点:
1, 每一个Android应用程序进程都有一个Dalvik虚拟机实例。
2, 虚拟机的进程和线程都是与目标机器本地操作系统的进程和线程一一对应的,由本地操作系统来管理。
Java代码根据所述进程运行在虚拟机里,C/C++在本地库中。JNI方法是直接在本地操作系统上执行的,而不是由Dalvik虚拟机解释器执行。由此也可看出,JNI方法是Android应用程序与本地操作系统直接进行通信的一个手段。那么如何将java代码和C/C++ 代码相关联起来呢?
2, 方法注册
方法注册目的:将Java的方法和C/C++方法通过JNI技术一一对应起来,这样才可以互相调用。有2种注册方法,静态注册和动态注册。在这里仅讨论android系统中常用的注册方法,动态注册。
2.1 注册核心类方法
zygote进程由init进程启动, zygote在内部会先启动Dalvik虚拟机(JNI环境),然后开始方法的注册,其它和本文无关的就不论述了。
1. /*static*/ intAndroidRuntime::startReg(JNIEnv* env)
2. {
3. androidSetCreateThreadFunc((android_create_thread_fn)javaCreateThreadEtc);
4.
5. env->PushLocalFrame(200);
6.
7. if(register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
8. env->PopLocalFrame(NULL);
9. return -1;
10. }
11. env->PopLocalFrame(NULL);
12.
13. //createJavaThread("fubar",quickTest, (void*) "hello");
14.
15. return 0;
16. }
17. static const RegJNIRec gRegJNI[] = {
18. REG_JNI(register_android_util_SeempLog),
19. REG_JNI(register_com_android_internal_os_RuntimeInit),
20. REG_JNI(register_android_os_SystemClock),
21. REG_JNI(register_android_os_MessageQueue),
22. ···
gRegJNI是一个全局变量的JNI方法注册函数表,通过register_jni_procs方法逐个调用,逐个注册。
23. static int register_jni_procs(const RegJNIRecarray[], size_t count, JNIEnv* env)
24. {
25. for(size_t i = 0; i < count; i++) {
26. if (array[i].mProc(env) < 0) {
27. #ifndef NDEBUG
28. ALOGD("----------!!! %s failedto load\n", array[i].mName);
29. #endif
30. return -1;
31. }
32. }
33. return 0;
34. }
我们抽取其中一个MessageQueue注册函数register_android_os_MessageQueue来具体分析,其他的注册函数原理都是一样的。
最后调用JNIHelp.cpp 的jniRegisterNativeMethods 方法完成注册。
35. int register_android_os_MessageQueue(JNIEnv*env) {