首页
社区
课程
招聘
[分享]Art虚拟机JNIEnv相关分析(2)Art虚拟机中JNINativeInterface初始化流程分析
发表于: 2021-4-14 10:58 3735

[分享]Art虚拟机JNIEnv相关分析(2)Art虚拟机中JNINativeInterface初始化流程分析

2021-4-14 10:58
3735

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版本的时候会被打开,所以这个地方我们只分析useruserdebug版本的流程。所以接下来将会执行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中进行日志输出。


                          原文链接


                          [培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

                          收藏
                          免费 0
                          支持
                          分享
                          最新回复 (0)
                          游客
                          登录 | 注册 方可回帖
                          返回
                          //