android runtime 创建流程

来源:互联网 发布:微社区 源码 编辑:程序博客网 时间:2024/06/01 10:22

在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为true310      } 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 AndroidRuntime35  {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 have957    // 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 will494      // 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继承自JavaVM1139  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, this693    // 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:继承自JNIEnv723      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实例。