接着前一篇博文 ART VM的启动流程,继续分析
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函数启动已经成功创建的虚拟机。