Android ART VM启动流程(六)

接着前一篇博文 ART VM的启动流程,继续分析

启动虚拟机的核心函数是startVM,

frameworks/base/core/jni/AndroidRuntime.cpp

int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote)
{
    /*
     * Initialize the VM.
     *
     * The JavaVM* is essentially per-process, and the JNIEnv* is per-thread.
     * If this call succeeds, the VM is ready, and we can start issuing
     * JNI calls.
     */
    if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
        ALOGE("JNI_CreateJavaVM failed\n");
        return -1;
    }
}

startVM的前半部分是在处理虚拟机的启动参数,处理完配置参数后,会调用libart.so提供的一个接口:JNI_CreateJavaVM函数。

在art虚拟机下,这个函数的实现在java_vm_ext.cc中

art/runtime/java_vm_ext.cc

// JNI Invocation interface.

extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
//解析虚拟机选项
  RuntimeOptions options;
  for (int i = 0; i < args->nOptions; ++i) {
    JavaVMOption* option = &args->options[i];
    options.push_back(std::make_pair(std::string(option->optionString), option->extraInfo));
  }
  bool ignore_unrecognized = args->ignoreUnrecognized;
//创建一个Runtime运行时对象
 if (!Runtime::Create(options, ignore_unrecognized)) {
    return JNI_ERR;
  }

  // Initialize native loader. This step makes sure we have
  // everything set up before we start using JNI.
  android::InitializeNativeLoader();

  Runtime* runtime = Runtime::Current();
//通过Runtime启动其管理的虚拟机
 bool started = runtime->Start();
  if (!started) {
    delete Thread::Current()->GetJniEnv();
    delete runtime->GetJavaVM();
    LOG(WARNING) << "CreateJavaVM failed";
    return JNI_ERR;
  }

  *p_env = Thread::Current()->GetJniEnv();
//获取已经启动完成的虚拟机实例,并通过p_vm这个指向指针的指针变量,把虚拟机实例传给AndroidRuntime中的变量JavaVM* AndroidRuntime::mJavaVM。
 *p_vm = runtime->GetJavaVM();
  return JNI_OK;
}

首先通过Runtime的create方法创建单例的Runtime对象,runtime负责提供art虚拟机的运行时环境,然后调用其init方法来初始化虚拟机。

art/runtime/runtime.cc

bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) {
  MemMap::Init();
  oat_file_manager_ = new OatFileManager;

  Thread::SetSensitiveThreadHook(runtime_options.GetOrDefault(Opt::HookIsSensitiveThread));
  Monitor::Init(runtime_options.GetOrDefault(Opt::LockProfThreshold));
  XGcOption xgc_option = runtime_options.GetOrDefault(Opt::GcOption);
//step1,创建堆管理对象。
  heap_ = new gc::Heap(runtime_options.GetOrDefault(Opt::MemoryInitialSize),
                       runtime_options.GetOrDefault(Opt::HeapGrowthLimit),
                       runtime_options.GetOrDefault(Opt::HeapMinFree),
                       runtime_options.GetOrDefault(Opt::HeapMaxFree),
                       runtime_options.GetOrDefault(Opt::HeapTargetUtilization),
                       runtime_options.GetOrDefault(Opt::ForegroundHeapGrowthMultiplier),
                       runtime_options.GetOrDefault(Opt::MemoryMaximumSize),
                       runtime_options.GetOrDefault(Opt::NonMovingSpaceCapacity),
                       runtime_options.GetOrDefault(Opt::Image),
                       runtime_options.GetOrDefault(Opt::ImageInstructionSet),
                       xgc_option.collector_type_,
                       runtime_options.GetOrDefault(Opt::BackgroundGc),
                       runtime_options.GetOrDefault(Opt::LargeObjectSpace),
                       runtime_options.GetOrDefault(Opt::LargeObjectThreshold),
                       runtime_options.GetOrDefault(Opt::ParallelGCThreads),
                       runtime_options.GetOrDefault(Opt::ConcGCThreads),
                       runtime_options.Exists(Opt::LowMemoryMode),
                       runtime_options.GetOrDefault(Opt::LongPauseLogThreshold),
                       runtime_options.GetOrDefault(Opt::LongGCLogThreshold),
                       runtime_options.Exists(Opt::IgnoreMaxFootprint),
                       runtime_options.GetOrDefault(Opt::UseTLAB),
                       xgc_option.verify_pre_gc_heap_,
                       xgc_option.verify_pre_sweeping_heap_,
                       xgc_option.verify_post_gc_heap_,
                       xgc_option.verify_pre_gc_rosalloc_,
                       xgc_option.verify_pre_sweeping_rosalloc_,
                       xgc_option.verify_post_gc_rosalloc_,
                       xgc_option.gcstress_,
                       runtime_options.GetOrDefault(Opt::EnableHSpaceCompactForOOM),
                       runtime_options.GetOrDefault(Opt::HSpaceCompactForOOMMinIntervalsMs));

  if (!heap_->HasBootImageSpace() && !allow_dex_file_fallback_) {
    LOG(ERROR) << "Dex file fallback disabled, cannot continue without image.";
    return false;
  }
//step2,创建java虚拟机对象
  java_vm_ = new JavaVMExt(this, runtime_options);

  Thread::Startup();
//step3,连接主线程
  // ClassLinker needs an attached thread, but we can't fully attach a thread without creating
  // objects. We can't supply a thread group yet; it will be fixed later. Since we are the main
  // thread, we do not get a java peer.
  Thread* self = Thread::Attach("main", false, nullptr, false);
  CHECK_EQ(self->GetThreadId(), ThreadList::kMainThreadId);
  CHECK(self != nullptr);

  // Set us to runnable so tools using a runtime can allocate and GC by default
  self->TransitionFromSuspendedToRunnable();

  // Now we're attached, we can take the heap locks and validate the heap.
  GetHeap()->EnableObjectValidation();
//step4,创建类连接器
  class_linker_ = new ClassLinker(intern_table_);
  if (GetHeap()->HasBootImageSpace()) {
    std::string error_msg;
//step5,初始化类连接器
   bool result = class_linker_->InitFromBootImage(&error_msg);
    {
      ScopedTrace trace2("MoveImageClassesToClassTable");
      GetClassLinker()->AddBootImageClassesToClassTable();
    }
  } else {
    std::vector<std::unique_ptr<const DexFile>> boot_class_path;
    if (runtime_options.Exists(Opt::BootClassPathDexList)) {
      boot_class_path.swap(*runtime_options.GetOrDefault(Opt::BootClassPathDexList));
    } else {
      OpenDexFiles(dex_filenames,
                   dex_locations,
                   runtime_options.GetOrDefault(Opt::Image),
                   &boot_class_path);
    }
    instruction_set_ = runtime_options.GetOrDefault(Opt::ImageInstructionSet);
    std::string error_msg;
    if (!class_linker_->InitWithoutImage(std::move(boot_class_path), &error_msg)) {
      LOG(ERROR) << "Could not initialize without image: " << error_msg;
      return false;
    }
  verifier::MethodVerifier::Init();
  return true;
}

step1,new gc::heap(),创建Heap对象,这是虚拟机管理对内存的起点。

step2,new JavaVmExt(),创建Java虚拟机实例。

step3,Thread::attach(),attach主线程,看下具体代码:

art/runtime/Thread.cc

Thread* Thread::Attach(const char* thread_name, bool as_daemon, jobject thread_group,
                       bool create_peer) {
//获取进程中单实例的runtime
  Runtime* runtime = Runtime::Current();
  Thread* self;
  {
    MutexLock mu(nullptr, *Locks::runtime_shutdown_lock_);
    if (runtime->IsShuttingDownLocked()) {
//如果runtime是关闭状态,线程就不能attach
      LOG(WARNING) << "Thread attaching while runtime is shutting down: " << thread_name;
      return nullptr;
    } else {
      Runtime::Current()->StartThreadBirth();
//新建一个线程类,执行其初始化
    self = new Thread(as_daemon);
      bool init_success = self->Init(runtime->GetThreadList(), runtime->GetJavaVM());
      Runtime::Current()->EndThreadBirth();
    }
  }
  self->InitStringEntryPoints();
//将线程的状态设置为knative,表示运行在native环境中
  CHECK_NE(self->GetState(), kRunnable);
  self->SetState(kNative);
  return self;
}

线程初始化的过程中,会为新线程分配一个自己的JNIEnvExt实例,因为虚拟机的每个线程都有自己独立的JNI环境,然后把它注册到Runtime的线程列表thread_list。

step4,new ClassLinker(),成功attach到runtime环境后,创建ClassLinker实例负责管理java class。

到这里,虚拟机的创建和初始化就完成了,接下来就是通过JNI_CreateJavaVm的start函数启动已经成功创建的虚拟机。


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值