-
-
[分享]Art虚拟机JNIEnv相关分析(2)Art虚拟机中JNINativeInterface初始化流程分析
-
发表于: 2021-4-14 10:58 3712
-
1.JNIEnv初始化
在文章"JNIEnv初始化分析"中已经分析了JNIEnv的初始化构造流程。最终JNIEnv初始化构造是在文件 art\runtime\thread.cc中的类中进行构造,关键代码如下:
bool Thread::Init(ThreadList* thread_list, JavaVMExt* java_vm, JNIEnvExt* jni_env_ext) { ... if (jni_env_ext != nullptr) { ... tlsPtr_.jni_env = jni_env_ext; } else { std::string error_msg; //创建JNIEnv结构并存储到线程局部存储变量中 tlsPtr_.jni_env = JNIEnvExt::Create(this, java_vm, &error_msg); ... } ... }
接下来分析JNIEnvExt中的JNINativeInterface是如何初始化的。
2.JNINativeInterface初始化流程分析
JNIEnvExt类的文件路径为:
art\runtime\jni\jni_env_ext.cc
(1).JNIEnvExt中的调用分析
在以上分析中JNIEnv通过调用JNIEnvExt::Create进行创建,在JNIEnvExt中的Create方法实现逻辑如下:
JNIEnvExt* JNIEnvExt::Create(Thread* self_in, JavaVMExt* vm_in, std::string* error_msg) { std::unique_ptr<JNIEnvExt> ret(new JNIEnvExt(self_in, vm_in, error_msg)); ... }
在以上代码中使用了new JNIEnvExt(self_in, vm_in, error_msg)进行初始化,下面是JNIEnvExt构造函数实现:
JNIEnvExt::JNIEnvExt(Thread* self_in, JavaVMExt* vm_in, std::string* error_msg) : self_(self_in), vm_(vm_in), local_ref_cookie_(kIRTFirstSegment), locals_(kLocalsInitial, kLocal, IndirectReferenceTable::ResizableCapacity::kYes, error_msg), monitors_("monitors", kMonitorsInitial, kMonitorsMax), critical_(0), check_jni_(false), runtime_deleted_(false) { ... //这个地方进行了JNINativeInterface的初始化,functions 定义在JNIEnv中 functions = GetFunctionTable(check_jni_); }
在以上代码调用中调用了GetFunctionTable()方法初始化JNIEnv中的functions变量,JNIEnv中的functions定义如下:
struct _JNIEnv { /* do not rename this; it does not seem to be entirely opaque */ const struct JNINativeInterface* functions; ... }
接下来分析一下GetFunctionTable方法中的实现。GetFunctionTable逻辑代码如下:
onst JNINativeInterface* JNIEnvExt::GetFunctionTable(bool check_jni) { ... //当前会根据chck_jni调用不同的JNINativeInterface初始化接口 return check_jni ? GetCheckJniNativeInterface() : GetJniNativeInterface(); }
check_jni在编译eng版本的时候会被打开,所以这个地方我们只分析user、userdebug版本的流程。所以接下来将会执行GetJniNativeInterface方法。
根据源码定位GetJniNativeInterface方法定义在如下文件:
art\runtime\jni\jni_internal.h
定义的代码内容如下:
const JNINativeInterface* GetJniNativeInterface();
该方法实现文件路径位于:
art\runtime\jni\jni_internal.cc
接下来分析jni_internal.cc中的流程。
(2).jni_internal.cc中的调用分析
在该文件中GetJniNativeInterface方法实现如下:
const JNINativeInterface* GetJniNativeInterface() { return &gJniNativeInterface;}
有以上代码分析可知返回的是gJniNativeInterface变量的值,该变量定义如下:
const JNINativeInterface gJniNativeInterface = { nullptr, // reserved0. nullptr, // reserved1. nullptr, // reserved2. nullptr, // reserved3. JNI::GetVersion, JNI::DefineClass, JNI::FindClass, ...}
有以上代码可以知道该变量为常量,使用一些列JNI类中的方法填充JNINativeInterface接口,从而完成JNIEnv中的JNINativeInterface初始化。
在jni_internal.cc中可以找到类JNI的定义实现。如下:
const JNINativeInterface gJniNativeInterface = { nullptr, // reserved0. nullptr, // reserved1. nullptr, // reserved2. nullptr, // reserved3. JNI::GetVersion, JNI::DefineClass, JNI::FindClass, ... }
以上代码可以看到JNI中真正实现了JNIEnv结构体中JNINativeInterface接口,我们平时调用的接口比如FindClass最终调用的是JNI::FindClass。
3.总结
art虚拟机中的JNIEnv中的各种接口最终实现位于"jni_internal.cc"中的class JNI中实现。
如果我们需要在系统中进行JNI trace,就可以在jni_internal.cc中进行日志输出。