android runtime 创建流程

在zygote进程启动过程中会创建art虚拟机,那我们就看一下art虚拟机是怎么创建出来的。

用户空间的init进程起来之后,会根据.xxxrc 文件中的配置,把相关进程运行起来,通过fork()和execve()来创建和加载对应的进程,我们锁熟悉的zygote进程也是在这个时候被运行起来的,zygote进程的前身是app_process,到了后面才把这个进程的名字改成zygote,可执行程序为 /system/bin/app_process32 或 /system/bin/app_process64 。

frameworks/base/cmds/app_process/app_main.cpp

186  int main(int argc, char* const argv[])
187  {
         ...
197      AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv)); //创建虚拟机实例
         ...
306      if (zygote) {
307          runtime.start("com.android.internal.os.ZygoteInit", args, zygote);//初始化并启动虚拟机
308      } else if (className) {
309          runtime.start("com.android.internal.os.RuntimeInit", args, zygote); //参数zygote为true
310      } else {
311          fprintf(stderr, "Error: no class name or --zygote supplied.\n");
312          app_usage();
313          LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
314          return 10;
315      }
316  }
所以接下来我们重点跟踪runtime.start()的流程
class AppRuntime : public AndroidRuntime
35  {
36  public:
37      AppRuntime(char* argBlockStart, const size_t argBlockLength)
38          : AndroidRuntime(argBlockStart, argBlockLength)
39          , mClass(NULL)
40      {
41      }
42  
43      void setClassNameAndArgs(const String8& className, int argc, char * const *argv) {
44          mClassName = className;
45          for (int i = 0; i < argc; ++i) {
46               mArgs.add(String8(argv[i]));
47          }
48      }
        ...
112  };

AppRuntime继承自AndroidRuntime,而AppRuntime 没有重写start()方法,所以跑到AndroidRuntime的start()里面。

frameworks/base/core/jni/AndroidRuntime.cpp

974  void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
975  {
976      ALOGD(">>>>>> START %s uid %d <<<<<<\n",
977              className != NULL ? className : "(unknown)", getuid());
          ...
1006      /* start the virtual machine */
1007      JniInvocation jni_invocation;
1008      jni_invocation.Init(NULL);  //加载libart.so 并绑定里面对应的函数
1009      JNIEnv* env;
1010      if (startVm(&mJavaVM, &env, zygote) != 0) {
1011          return;
1012      }
          ...
1018      if (startReg(env) < 0) { //注册系统的jni函数
1019          ALOGE("Unable to register all android natives\n");
1020          return;
1021      }
          ...
1050      char* slashClassName = toSlashClassName(className);
1051      jclass startClass = env->FindClass(slashClassName);
1052     if (startClass == NULL) {
1053         ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
1054          /* keep going */
1055      } else {
1056          jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
1057              "([Ljava/lang/String;)V"); //查找java 类里面的main()函数
1058          if (startMeth == NULL) {
1059              ALOGE("JavaVM unable to find main() in '%s'\n", className);
1060              /* keep going */
1061          } else {
1062              env->CallStaticVoidMethod(startClass, startMeth, strArray); //执行main()函数
1068          }
1069      }
          ...
1072      ALOGD("Shutting down VM\n"); //如果java里面的main()跑完了,表示进程结束了,可以销毁虚拟机
1073      if (mJavaVM->DetachCurrentThread() != JNI_OK)
1074          ALOGW("Warning: unable to detach main thread\n");
1075      if (mJavaVM->DestroyJavaVM() != 0)
1076          ALOGW("Warning: VM did not shut down cleanly\n");
1077  }

加载libart.so过程分析

libnativehelper/ JniInvocation.cpp

static const char* kLibraryFallback = "libart.so";

bool JniInvocation::Init(const char* library) {
  ...
  const int kDlopenFlags = RTLD_NOW | RTLD_NODELETE;
  handle_ = dlopen(library, kDlopenFlags); //library 默认就是libart.so
  if (handle_ == NULL) {
    if (handle_ == NULL) {
    if (strcmp(library, kLibraryFallback) == 0) {
      // Nothing else to try.
      ALOGE("Failed to dlopen %s: %s", library, dlerror());
      return false;
    }
    ...
    library = kLibraryFallback;
    handle_ = dlopen(library, kDlopenFlags); //如果上面是其他library并且加载失败,尝试加载libart.so
    ...
  }
  if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetDefaultJavaVMInitArgs_),
                  "JNI_GetDefaultJavaVMInitArgs")) {//绑定library 中对应的函数
    return false;
  }
  if (!FindSymbol(reinterpret_cast<void**>(&JNI_CreateJavaVM_),
                  "JNI_CreateJavaVM")) { //绑定library 中对应的函数
    return false;
  }
  if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetCreatedJavaVMs_),
                  "JNI_GetCreatedJavaVMs")) { //绑定library 中对应的函数
    return false;
  }
  return true;
}

跑完JniInvocation的初始化函数,也就是加载好libart.so库后,开始跑startVM()。

frameworks/base/core/jni/AndroidRuntime.cpp

581  int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote)
582  {
583      JavaVMInitArgs initArgs;
584      char propBuf[PROPERTY_VALUE_MAX];
585      char stackTraceFileBuf[sizeof("-Xstacktracefile:")-1 + PROPERTY_VALUE_MAX];
586      char jniOptsBuf[sizeof("-Xjniopts:")-1 + PROPERTY_VALUE_MAX];
587      char heapstartsizeOptsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];
588      char heapsizeOptsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX];
589      char heapgrowthlimitOptsBuf[sizeof("-XX:HeapGrowthLimit=")-1 + PROPERTY_VALUE_MAX];
590      char heapminfreeOptsBuf[sizeof("-XX:HeapMinFree=")-1 + PROPERTY_VALUE_MAX];
591      char heapmaxfreeOptsBuf[sizeof("-XX:HeapMaxFree=")-1 + PROPERTY_VALUE_MAX];
592      char usejitOptsBuf[sizeof("-Xusejit:")-1 + PROPERTY_VALUE_MAX];

         ...前面设置了一大推参数,然后调用JNI_CreateJavaVM()创建虚拟机,并传入参数
933      if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
934          ALOGE("JNI_CreateJavaVM failed\n");
935          return -1;
936      }
937  
938      return 0;
939  }

JNI_CreateJavaVM() 调用到JniInvocation中的JNI_CreateJavaVM()

libnativehelper/ JniInvocation.cpp

jint JniInvocation::JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
  return JNI_CreateJavaVM_(p_vm, p_env, vm_args);
}

JNI_CreateJavaVM_()指向的函数就是libart.so中的JNI_CreateJavaVM(),前面init()的时候进行了绑定(就是给JNI_CreateJavaVM_这个函数指针赋值)。

对应的函数定义在  art/runtime/java_vm_ext.cc

939  extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
940    ScopedTrace trace(__FUNCTION__);
941    const JavaVMInitArgs* args = static_cast<JavaVMInitArgs*>(vm_args);
       ...
946    RuntimeOptions options;
947    for (int i = 0; i < args->nOptions; ++i) {
948      JavaVMOption* option = &args->options[i];
         //把参数转成键值对的形式
949      options.push_back(std::make_pair(std::string(option->optionString), option->extraInfo));
950    }
951    bool ignore_unrecognized = args->ignoreUnrecognized;
952    if (!Runtime::Create(options, ignore_unrecognized)) {//创建Runtime 实例
953      return JNI_ERR;
954    }
955  
956    // Initialize native loader. This step makes sure we have
957    // everything set up before we start using JNI.
958    android::InitializeNativeLoader();
959  
960    Runtime* runtime = Runtime::Current();
961    bool started = runtime->Start();  //启动虚拟机
962    if (!started) {
963      delete Thread::Current()->GetJniEnv();
964      delete runtime->GetJavaVM();
965      LOG(WARNING) << "CreateJavaVM failed";
966      return JNI_ERR;
967    }
968    //返回创建的JavaVM 和 JNIEnv 
969    *p_env = Thread::Current()->GetJniEnv();
970    *p_vm = runtime->GetJavaVM();
971    return JNI_OK;
972  }

我们接下来看到Runtime::Create()做了什么事

art/runtime/runtime.cc

486  bool Runtime::Create(RuntimeArgumentMap&& runtime_options) {
487    // TODO: acquire a static mutex on Runtime to avoid racing.
488    if (Runtime::instance_ != nullptr) { //如果前面有创建过了,直接返回
489      return false;
490    }
491    instance_ = new Runtime;  //真正创建出Runtime 实例,在一个进程中只有一个这样的实例
492    if (!instance_->Init(std::move(runtime_options))) { //调用init()函数进行初始化
493      // TODO: Currently deleting the instance will abort the runtime on destruction. Now This will
494      // leak memory, instead. Fix the destructor. b/19100793.
495      // delete instance_;
496      instance_ = nullptr;
497      return false;
498    }
499    return true;
500  }
501  
502  bool Runtime::Create(const RuntimeOptions& raw_options, bool ignore_unrecognized) {
503    RuntimeArgumentMap runtime_options;
504    return ParseOptions(raw_options, ignore_unrecognized, &runtime_options) &&
505        Create(std::move(runtime_options));
506  }
所以接下来进入到init()函数里面

932  bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) {
       ... 
941    MemMap::Init();  //创建multimap
       ...
       //这个十分重要,后面的博客在分析
1015    heap_ = new gc::Heap(runtime_options.GetOrDefault(Opt::MemoryInitialSize),
        ...
1046    if (!heap_->HasBootImageSpace() && !allow_dex_file_fallback_) {
1047      LOG(ERROR) << "Dex file fallback disabled, cannot continue without image.";
1048      return false;
1049    }
        ...
1083    BlockSignals();
1084    InitPlatformSignalHandlers();
        ...
1124        if (implicit_so_checks_) {
1125          new StackOverflowHandler(&fault_manager);
1126        } 
1128        if (implicit_null_checks_) {
1129          new NullPointerHandler(&fault_manager);
1130        } 
1132        if (kEnableJavaStackTraceHandler) {
1133          new JavaStackTraceHandler(&fault_manager);
1134        }
        ...
1138    java_vm_ = new JavaVMExt(this, runtime_options); //创建JavaVMExt实例,JavaVMExt继承自JavaVM
1139  
1140    Thread::Startup();
        ...
1145    Thread* self = Thread::Attach("main", false, nullptr, false);//将JavaVM和当前线程绑定
        ...
1156    class_linker_ = new ClassLinker(intern_table_); //创建ClassLinker实例
1157    if (GetHeap()->HasBootImageSpace()) {
1158      std::string error_msg;
1159      bool result = class_linker_->InitFromBootImage(&error_msg);
         ...
1187    } else {
         ...
1223    }
1310    return true;
1311  }

因为heap 的内容太多了,java 对象就分配在这个内存区域中,heap 又被划分为不同的区域,对应不同的内存管理策略。

继续看一下Thread::Attach()又做了那些事

art/runtime/thread.cc

732  Thread* Thread::Attach(const char* thread_name, bool as_daemon, jobject thread_group,
733                         bool create_peer) {
734    Runtime* runtime = Runtime::Current(); //因为前面创建了Runtime,并且是一个全局的单例,所以通过Current()可以得到
735    if (runtime == nullptr) {
736      LOG(ERROR) << "Thread attaching to non-existent runtime: " << thread_name;
737      return nullptr;
738    }
739    Thread* self;
740    {
741      MutexLock mu(nullptr, *Locks::runtime_shutdown_lock_);
742      if (runtime->IsShuttingDownLocked()) {
743        LOG(WARNING) << "Thread attaching while runtime is shutting down: " << thread_name;
744        return nullptr;
745      } else {
746        Runtime::Current()->StartThreadBirth();
747        self = new Thread(as_daemon); //创建了一个Thread实例,这里的Thread是用来描述线程
748        bool init_success = self->Init(runtime->GetThreadList(), runtime->GetJavaVM()); //调用其init()函数
749        Runtime::Current()->EndThreadBirth();
750        if (!init_success) {
751          delete self;
752          return nullptr;
753        }
754      }
755    }
       ...
805    return self;
806  }

接下来看Init()里面做了什么

685  bool Thread::Init(ThreadList* thread_list, JavaVMExt* java_vm, JNIEnvExt* jni_env_ext) {
       ...
692    // Set pthread_self_ ahead of pthread_setspecific, that makes Thread::Current function, this
693    // avoids pthread_self_ ever being invalid when discovered from Thread::Current().
694    tlsPtr_.pthread_self = pthread_self();
       ...
698    if (!InitStackHwm()) {
699      return false;
700    }
701    InitCpu();
702    InitTlsEntryPoints(); //初始化外部库函数调用跳转表
703    RemoveSuspendTrigger();
704    InitCardTable();
705    InitTid();
706    interpreter::InitInterpreterTls(this); //初始化解释器调用跳转表
       ...
717    if (jni_env_ext != nullptr) {
718      DCHECK_EQ(jni_env_ext->vm, java_vm);
719      DCHECK_EQ(jni_env_ext->self, this);
720      tlsPtr_.jni_env = jni_env_ext;
721    } else {
722      tlsPtr_.jni_env = JNIEnvExt::Create(this, java_vm); //创建一个JNIEnvExt:实例,JNIEnvExt:继承自JNIEnv
723      if (tlsPtr_.jni_env == nullptr) {
724        return false;
725      }
726    }
728    thread_list->Register(this);  //将thread 加入到thread_list中,thread_list在runtime中创建
729    return true;
730  }

在jni中我们经常用到JNIEnv 的相关函数,那么这些函数的定义在哪里呢?接下来看一下JNIEnvExt::create()做了什么。

art/runtime/jni_env_ext.c

48  JNIEnvExt* JNIEnvExt::Create(Thread* self_in, JavaVMExt* vm_in) {
49    std::unique_ptr<JNIEnvExt> ret(new JNIEnvExt(self_in, vm_in));
50    if (CheckLocalsValid(ret.get())) {
51      return ret.release();
52    }
53    return nullptr;
54  }
55  // JNIEnvExt构造函数如下
56  JNIEnvExt::JNIEnvExt(Thread* self_in, JavaVMExt* vm_in)
57      : self(self_in),
58        vm(vm_in),
59        local_ref_cookie(IRT_FIRST_SEGMENT),
60        locals(kLocalsInitial, kLocalsMax, kLocal, false),
61        check_jni(false),
62        runtime_deleted(false),
63        critical(0),
64        monitors("monitors", kMonitorsInitial, kMonitorsMax) {
65    functions = unchecked_functions = GetJniNativeInterface();  //返回一个函数指针结构体
66    if (vm->IsCheckJniEnabled()) {
67      SetCheckJniEnabled(true);
68    }
69  }
那么functions绑定了什么呢?

art/runtime/jni_internal.cc

2731  const JNINativeInterface* GetJniNativeInterface() {
2732    return &gJniNativeInterface;
2733  }

 
2495  const JNINativeInterface gJniNativeInterface = {
2496    nullptr,  // reserved0.
2497    nullptr,  // reserved1.
2498    nullptr,  // reserved2.
2499    nullptr,  // reserved3.
2500    JNI::GetVersion,
2501    JNI::DefineClass,
2502    JNI::FindClass,
        ...
2637    JNI::CallStaticVoidMethod,
        ...
2715    JNI::GetJavaVM,
        ...
2729  };

所以我们在jni中调用JNIEnv 的函数对应的实现就在这里呀,比如FindClass()。

art/runtime/jni_internal.cc

338    static jclass FindClass(JNIEnv* env, const char* name) {
339      CHECK_NON_NULL_ARGUMENT(name);
340      Runtime* runtime = Runtime::Current();
341      ClassLinker* class_linker = runtime->GetClassLinker();
342      std::string descriptor(NormalizeJniClassDescriptor(name));
343      ScopedObjectAccess soa(env);
344      mirror::Class* c = nullptr;
345      if (runtime->IsStarted()) {
346        StackHandleScope<1> hs(soa.Self());
347        Handle<mirror::ClassLoader> class_loader(hs.NewHandle(GetClassLoader(soa)));
348        c = class_linker->FindClass(soa.Self(), descriptor.c_str(), class_loader);
349      } else {
350        c = class_linker->FindSystemClass(soa.Self(), descriptor.c_str());
351      }
352      return soa.AddLocalReference<jclass>(c);
353    }

到这里我们知道art虚拟机对应是Runtime 这个类,并且是一个单例模式,也就是一个进程(zygote进程或zygote子进程)中 只有一个Runtime实例。




版权声明:本文为xiongtiancheng原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。