一. Zygote啟動(dòng)過程中的創(chuàng)建虛擬機(jī)過程
Zygote的代碼位于/framework/base/cmds/app_process/app_main.cpp
int main(int argc, char* const argv[])
{
...
//[1.1]
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
... // handle args
if (zygote) {
//[1.2]
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (className) {
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
return 10;
}
}
main
方法中省略的代碼中主要在處理傳入的參數(shù), 從而確定當(dāng)前是否要執(zhí)行zygote的邏輯以及啟動(dòng)zygote時(shí)是否需要啟動(dòng)system_server
, 這里主要兩個(gè)關(guān)鍵調(diào)用:
-
AppRuntime runtime(...)
這行代碼創(chuàng)建了一個(gè)AppRuntime
對(duì)象,AppRuntime繼承自AndroidRuntime
-
runtime.start(...)
調(diào)用AppRuntime的start
方法,由于AppRuntime并沒有重寫父類的start方法,所以這里實(shí)際調(diào)用的是AndroidRuntime::start(...)
1.1 AndroidRuntime
AppRuntime
的定義就在app_main.cpp
中,其構(gòu)造函數(shù)為:
AppRuntime(char* argBlockStart, const size_t argBlockLength)
: AndroidRuntime(argBlockStart, argBlockLength)
, mClass(NULL){}
可以看到AppRuntime的構(gòu)造函數(shù)沒做任何事,主要就是調(diào)用父類AndroidRuntime
的構(gòu)造函數(shù), AndroidRuntime
定義在/framework/base/include/android_runtime/AndroidRuntime.h
,對(duì)應(yīng)的源文件在/framework/base/core/jni/AndroidRuntime.cpp
//全局變量
static AndroidRuntime* gCurRuntime = NULL;
AndroidRuntime::AndroidRuntime(char* argBlockStart, const size_t argBlockLength) :
mExitWithoutCleanup(false),
mArgBlockStart(argBlockStart),
mArgBlockLength(argBlockLength)
{
SkGraphics::Init();
// mOptions的類型是:Vector<JavaVMOption>
mOptions.setCapacity(20);
assert(gCurRuntime == NULL); // one per process
gCurRuntime = this;
}
1.2 AndroidRuntime::start
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
... //設(shè)置ANDROID_ROOT
/* 啟動(dòng)虛擬機(jī) */
//[1.3]
JniInvocation jni_invocation;
//[1.4]
jni_invocation.Init(NULL);
JNIEnv* env;
//[1.5], mJavaVM是AndroidRuntime的static變量,初始化為NULL
if (startVm(&mJavaVM, &env, zygote) != 0) {
return;
}
//[1.6]
onVmCreated(env);
/* 注冊android相關(guān)的jni方法 */
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
... //調(diào)用com.android.internal.os.ZygoteInit或者RuntimeInit的main方法
if (mJavaVM->DetachCurrentThread() != JNI_OK)
ALOGW("Warning: unable to detach main thread\n");
if (mJavaVM->DestroyJavaVM() != 0)
ALOGW("Warning: VM did not shut down cleanly\n");
}
1.3 JniInvocation::JniInvocation
JniInvocation::JniInvocation() :
handle_(NULL),
JNI_GetDefaultJavaVMInitArgs_(NULL),
JNI_CreateJavaVM_(NULL),
JNI_GetCreatedJavaVMs_(NULL) {
LOG_ALWAYS_FATAL_IF(jni_invocation_ != NULL, "JniInvocation instance already initialized");
jni_invocation_ = this;
}
JniInvocation
類的頭文件和源文件分別在/libnativehelper/include/nativehelper/JniInvocation.h
,/libnativehelper/JniInvocation.cpp
.
JniInvocation
中有三個(gè)重要的變量:
-
JNI_CreateJavaVM_
(創(chuàng)建虛擬機(jī)實(shí)例) -
JNI_GetCreatedJavaVMs_
(獲取創(chuàng)建的虛擬機(jī)實(shí)例) -
JNI_GetDefaultJavaVMInitArgs_
(獲取虛擬機(jī)的默認(rèn)初始化參數(shù))
這三個(gè)變量是標(biāo)準(zhǔn)的Java虛擬機(jī)的接口,也就是說實(shí)現(xiàn)了這個(gè)三個(gè)接口,就可以實(shí)現(xiàn)一個(gè)Java虛擬機(jī),具體可參考羅升陽的博客.
JniInvocation
的構(gòu)造函數(shù)中初始化這三個(gè)變量為NULL
1.4 JniInvocation::Init
bool JniInvocation::Init(const char* library) {
#ifdef __ANDROID__
char buffer[PROP_VALUE_MAX];
#else
char* buffer = NULL;
#endif
//由于傳入的library是NULL,所以最后實(shí)際獲取到的library是libart.so
library = GetLibrary(library, buffer);
const int kDlopenFlags = RTLD_NOW | RTLD_NODELETE;
handle_ = dlopen(library, kDlopenFlags);
if (handle_ == NULL) {
... //打開libart.so失敗,直接返回;如果打開其他library失敗,則嘗試打開libart.so
}
//尋找并導(dǎo)出JNI_GetDefaultJavaVMInitArgs_
if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetDefaultJavaVMInitArgs_),
"JNI_GetDefaultJavaVMInitArgs")) {
return false;
}
//尋找并導(dǎo)出JNI_CreateJavaVM_
if (!FindSymbol(reinterpret_cast<void**>(&JNI_CreateJavaVM_),
"JNI_CreateJavaVM")) {
return false;
}
//尋找并導(dǎo)出JNI_GetCreatedJavaVMs_
if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetCreatedJavaVMs_),
"JNI_GetCreatedJavaVMs")) {
return false;
}
return true;
}
bool JniInvocation::FindSymbol(void** pointer, const char* symbol) {
*pointer = dlsym(handle_, symbol);
... // handle error
return true;
}
JniInvocation::Init
的主要工作就是通過dlopen
函數(shù)打開libart.so
,之后利用dlsym
函數(shù)尋找并導(dǎo)出Java虛擬機(jī)的三個(gè)接口,這樣就可以通過這三個(gè)接口創(chuàng)建并訪問虛擬機(jī)
1.5 AndroidRuntime::startVm
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote)
{
... //解析啟動(dòng)參數(shù)
initArgs.version = JNI_VERSION_1_4;
initArgs.options = mOptions.editArray();
initArgs.nOptions = mOptions.size();
initArgs.ignoreUnrecognized = JNI_FALSE;
/**
* 創(chuàng)建虛擬機(jī), 每一個(gè)進(jìn)程有一個(gè)JavaVM*, 每一個(gè)線程有一個(gè)JNIEnv*
*/
//[1.5.1]
if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
ALOGE("JNI_CreateJavaVM failed\n");
return -1;
}
return 0;
}
Android::startVm
主要做了兩項(xiàng)工作:
- 解析虛擬機(jī)啟動(dòng)參數(shù)
- 調(diào)用
JNI_CreateJavaVM
創(chuàng)建虛擬機(jī).源碼的注釋中清楚地說明了創(chuàng)建虛擬機(jī)后每一個(gè)進(jìn)程都應(yīng)該具有一個(gè)JavaVM指針,而每一個(gè)線程都具有一個(gè)JNIEnv指針.JNI_CreateJavaVM
實(shí)現(xiàn)在/libnativehelper/JniInvocation.cpp
中,其主要邏輯就是返回之前從libart.so
中導(dǎo)出的JNI_CreateJavaVM_
接口,即JNI_CreateJavaVM
的真正實(shí)現(xiàn)是由libart.so
完成的
1.5.1 JniInvocation::JNI_CreateJavaVM
extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
return JniInvocation::GetJniInvocation().JNI_CreateJavaVM(p_vm, p_env, vm_args);
}
jint JniInvocation::JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
return JNI_CreateJavaVM_(p_vm, p_env, vm_args);
}
JNI_CreateJavaVM_
就是之前在JniInvocation::Init
中導(dǎo)出的函數(shù)指針
1.6 AppRuntime::onVmCreated
AndroidRuntime::onVmCreated
是一個(gè)虛方法,AndroidRuntime類并沒有實(shí)現(xiàn)這個(gè)方法,具體實(shí)現(xiàn)是由子類AppRuntime
實(shí)現(xiàn)
virtual void onVmCreated(JNIEnv* env){
if (mClassName.isEmpty()) {
return; // Zygote. Nothing to do here.
}
char* slashClassName = toSlashClassName(mClassName.string());
mClass = env->FindClass(slashClassName);
if (mClass == NULL) {
ALOGE("ERROR: could not find class '%s'\n", mClassName.string());
}
free(slashClassName);
mClass = reinterpret_cast<jclass>(env->NewGlobalRef(mClass));
}
從代碼中可以看出,如果是Zygote的啟動(dòng),則onVmCreated
實(shí)際什么也沒有做
二. libart.so中的JNI_CreateJavaVM
libart.so的代碼都位于/art
目錄下,而JNI_CreateJavaVM
定義在/art/runtime/java_vm_ext.cc
中:
extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
ScopedTrace trace(__FUNCTION__);
const JavaVMInitArgs* args = static_cast<JavaVMInitArgs*>(vm_args);
//檢查Jni版本號(hào)
if (IsBadJniVersion(args->version)) {
LOG(ERROR) << "Bad JNI version passed to CreateJavaVM: " << args->version;
return JNI_EVERSION;
}
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;
//[2.1] 創(chuàng)建Runtime
if (!Runtime::Create(options, ignore_unrecognized)) {
return JNI_ERR;
}
//初始化native loader, 確保在使用JNI之前所需的環(huán)境都已經(jīng)設(shè)置好
android::InitializeNativeLoader();
Runtime* runtime = Runtime::Current();
//[2.2] 啟動(dòng)Runtime
bool started = runtime->Start();
if (!started) {
delete Thread::Current()->GetJniEnv();
delete runtime->GetJavaVM();
LOG(WARNING) << "CreateJavaVM failed";
return JNI_ERR;
}
//獲取JNIEnv和JavaVM,返回給上層
*p_env = Thread::Current()->GetJniEnv();
*p_vm = runtime->GetJavaVM();
return JNI_OK;
}
2.1 Runtime::Create
代碼位于/art/runtime/runtime.cc
bool Runtime::Create(const RuntimeOptions& raw_options, bool ignore_unrecognized) {
RuntimeArgumentMap runtime_options;
//首先調(diào)用ParseOptions,之后再調(diào)用另一個(gè)重載版本的Create
return ParseOptions(raw_options, ignore_unrecognized, &runtime_options) &&
Create(std::move(runtime_options));
}
bool Runtime::Create(RuntimeArgumentMap&& runtime_options) {
if (Runtime::instance_ != nullptr) {
return false;
}
instance_ = new Runtime;
//調(diào)用Runtime::Init(), [2.1.1]
if (!instance_->Init(std::move(runtime_options))) {
// TODO: Currently deleting the instance will abort the runtime on destruction. Now This will
// leak memory, instead. Fix the destructor. b/19100793.
// delete instance_;
instance_ = nullptr;
return false;
}
return true;
}
ParseOptions()
最終會(huì)調(diào)用ParsedOptions::DoParse
方法(/art/runtime/parsed_options.cc
),主要就是用來解析傳入的啟動(dòng)參數(shù),這里暫時(shí)先不分析其主要邏輯.從代碼中可以看到Create
函數(shù)主要操作視調(diào)用Runtime::Init
函數(shù)
2.1.1 Runtime::Init
bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) {
RuntimeArgumentMap runtime_options(std::move(runtime_options_in));
ScopedTrace trace(__FUNCTION__);
MemMap::Init();
using Opt = RuntimeArgumentMap;
QuasiAtomic::Startup();
//創(chuàng)建OatFileManager, OatFileManager主要用來加載oat文件
oat_file_manager_ = new OatFileManager;
Thread::SetSensitiveThreadHook(runtime_options.GetOrDefault(Opt::HookIsSensitiveThread));
Monitor::Init(runtime_options.GetOrDefault(Opt::LockProfThreshold));
//從傳入的參數(shù)中初始化boot_class_path_string_, class_path_string_, patchoat_executable_等變量
//創(chuàng)建monitor_list_, monitor_pool_, thread_list_, intern_table_
//繼續(xù)獲取一些基本變量
...
//查看參數(shù)中是否指定了解釋執(zhí)行,如果指定,則告知虛擬機(jī)所有代碼都是解釋執(zhí)行
if (runtime_options.GetOrDefault(Opt::Interpret)) {
GetInstrumentation()->ForceInterpretOnly();
}
//仍然是從傳入的參數(shù)中初始化一些基礎(chǔ)變量, 并獲取CompilerFilter
...
//創(chuàng)建堆Heap
heap_ = new gc::Heap(...);
if (!heap_->HasBootImageSpace() && !allow_dex_file_fallback_) {
LOG(ERROR) << "Dex file fallback disabled, cannot continue without image.";
return false;
}
... //獲取dump_gc_performance_on_shutdown_, 配置Jdwp
//創(chuàng)建JIT選項(xiàng),JIT是7.0中新增的,用來提升代碼執(zhí)行效率
jit_options_.reset(jit::JitOptions::CreateFromRuntimeArguments(runtime_options));
//如果此時(shí)是dex2oat程序,dex2oat執(zhí)行時(shí)也會(huì)創(chuàng)建一個(gè)Runtime用來編譯dex文件,此時(shí)不需要開啟JIT選項(xiàng)
if (IsAotCompiler()) {
jit_options_->SetUseJitCompilation(false);
jit_options_->SetSaveProfilingInfo(false);
}
//創(chuàng)建lamba_box_table, arena_pool_, jit_arena_pool_, 如果是64位架構(gòu)且當(dāng)前是dex2oat, 獲取low_4gb_arena_pool_
...
//創(chuàng)建線性分配器linear_alloc_,LinearAlloc創(chuàng)建時(shí)會(huì)用到上面創(chuàng)建的low_4gb_arena_pool_(64位架構(gòu)且是dex2oat時(shí))或者arena_pool_
linear_alloc_.reset(CreateLinearAlloc());
BlockSignals();
//初始化SIGSEGV信號(hào)處理函數(shù)為HandleUnexpectedSignal
InitPlatformSignalHandlers();
//arm, arm64, x86, mips, mips64, thumb2, x86_64架構(gòu)下,
//implicit_null_checks_ = true
//implicit_so_checks_ !(RUNNING_ON_MEMORY_TOOL && kMemoryToolIsValgrind)
....
... //處理no_sig_chain = false時(shí)的情況(no_sig_chain在之前根據(jù)傳入的參數(shù)獲取)
//創(chuàng)建JavaVMExt
java_vm_ = new JavaVMExt(this, runtime_options);
//創(chuàng)建線程TLS
Thread::Startup();
//attach線程, 創(chuàng)建Thread對(duì)象,初始化Thread對(duì)象
Thread* self = Thread::Attach("main", false, nullptr, false);
// Set us to runnable so tools using a runtime can allocate and GC by default
self->TransitionFromSuspendedToRunnable();
// 驗(yàn)證heap
GetHeap()->EnableObjectValidation();
//創(chuàng)建ClassLinker
class_linker_ = new ClassLinker(intern_table_);
if (GetHeap()->HasBootImageSpace()) {
...
bool result = class_linker_->InitFromBootImage(&error_msg);
...
if (boot_class_path_string_.empty()) {
// 如果bootclasspath沒有顯示指定,則從加載的dex文件列表中進(jìn)行構(gòu)造,這里的dex文件列表是系統(tǒng)構(gòu)建時(shí)已經(jīng)創(chuàng)建好的眾多預(yù)加載的文件
...
}
// 在intern_table_中添加boot image space;將boo image space添加到當(dāng)前ClassLinker的ClassTable中
...
} else {
....
if (!class_linker_->InitWithoutImage(std::move(boot_class_path), &error_msg)) {
return false;
}
...
}
... //MethodTrace, ProfilerOptions, Trace
//提前分配一個(gè)OutOfMemoryError
self->ThrowNewException("Ljava/lang/OutOfMemoryError;",
"OutOfMemoryError thrown while trying to throw OutOfMemoryError; "
"no stack trace available");
pre_allocated_OutOfMemoryError_ = GcRoot<mirror::Throwable>(self->GetException());
self->ClearException();
//提前分配一個(gè)NoClassDefFoundError
self->ThrowNewException("Ljava/lang/NoClassDefFoundError;",
"Class not found using the boot class loader; no stack trace available");
pre_allocated_NoClassDefFoundError_ = GcRoot<mirror::Throwable>(self->GetException());
self->ClearException();
... //從傳入的參數(shù)中獲取native_bridge_file_name
return true;
}
Runtime::Init
方法代碼量較大,整個(gè)過程中創(chuàng)建或者初始化了很多工具組件如MemMap, QuasiAtomic
等,并且從傳入的參數(shù)依次獲取了一些基礎(chǔ)變量如boot_class_path_string_, class_path_string_
等,之后還設(shè)置信號(hào)處理函數(shù)等,不過整體來看Init
方法的主要邏輯很清楚,分別做了以下幾件事:
- 創(chuàng)建
OatFileManager
對(duì)象,OatFileManager
是在7.0中新增的工具類,Runtime在解析讀取oat文件都是通過這個(gè)工具類完成 - 創(chuàng)建了
Heap
(整個(gè)創(chuàng)建過程比較冗長,復(fù)雜) - 根據(jù)傳入?yún)?shù)配置JIT選項(xiàng),如果當(dāng)前是dex2oat則不配置JIT
- 創(chuàng)建
LinearAlloc
- 創(chuàng)建
JavaVMExt
- 創(chuàng)建一個(gè)線程,同時(shí)attach線程(attach的過程實(shí)際就是創(chuàng)建Thread對(duì)象并初始化Thread對(duì)象的過程)
- 創(chuàng)建
ClassLinker
,如果有BootImageSpace
則調(diào)用ClassLinker::InitFromBootImage
完成ClassLinker的初始化;如果沒有BootImageSpace
,則調(diào)用ClassLinker::InitWithoutImage
來完成初始化 - 提前分配一個(gè)
OutOfMemoryError
和NoClassDefFoundError
Heap
的創(chuàng)建過程比較復(fù)雜,個(gè)人覺得需要單獨(dú)整理一個(gè)篇幅來學(xué)習(xí),OatFileManager
和LinearAlloc
的構(gòu)造函數(shù)都很簡單, 另外ClassLinker
的初始化過程也較為繁瑣,加上ClassLinker
類比較重要,同樣需要單獨(dú)的篇幅來學(xué)習(xí)
2.1.2 JavaVMExt::JavaVMExt
JavaVMExt
的源文件是/art/runtime/java_vm_ext.cc
,JavaVMExt
繼承自JavaVM
:
class JavaVMExt : public JavaVM {
...
};
JavaVM
定義在/libnativehelper/include/nativehelper/jni.h
中
JavaVMExt::JavaVMExt(Runtime* runtime, const RuntimeArgumentMap& runtime_options)
: runtime_(runtime),
check_jni_abort_hook_(nullptr),
check_jni_abort_hook_data_(nullptr),
check_jni_(false), // Initialized properly in the constructor body below.
force_copy_(runtime_options.Exists(RuntimeArgumentMap::JniOptsForceCopy)),
tracing_enabled_(runtime_options.Exists(RuntimeArgumentMap::JniTrace)
|| VLOG_IS_ON(third_party_jni)),
trace_(runtime_options.GetOrDefault(RuntimeArgumentMap::JniTrace)),
globals_lock_("JNI global reference table lock"),
globals_(gGlobalsInitial, gGlobalsMax, kGlobal),
libraries_(new Libraries),
unchecked_functions_(&gJniInvokeInterface),
weak_globals_lock_("JNI weak global reference table lock", kJniWeakGlobalsLock),
weak_globals_(kWeakGlobalsInitial, kWeakGlobalsMax, kWeakGlobal),
allow_accessing_weak_globals_(true),
weak_globals_add_condition_("weak globals add condition", weak_globals_lock_) {
functions = unchecked_functions_;
SetCheckJniEnabled(runtime_options.Exists(RuntimeArgumentMap::CheckJni));
}
可以看到,JavaVMExt
的構(gòu)造函數(shù)存儲(chǔ)了Runtme
指針,之后初始化了自身變量
2.1.3 Thread::Startup
void Thread::Startup() {
...
//調(diào)用pthread_key_create來創(chuàng)建線程私有數(shù)據(jù)TLS
CHECK_PTHREAD_CALL(pthread_key_create, (&Thread::pthread_key_self_, Thread::ThreadExitCallback),
"self key");
...
}
2.1.4 Thread::Attach
Thread* Thread::Attach(const char* thread_name, bool as_daemon, jobject thread_group,
bool create_peer) {
Runtime* runtime = Runtime::Current();
...
Thread* self;
{
MutexLock mu(nullptr, *Locks::runtime_shutdown_lock_);
if (runtime->IsShuttingDownLocked()) {
...
return nullptr;
} else {
Runtime::Current()->StartThreadBirth();
//創(chuàng)建Thread對(duì)象
self = new Thread(as_daemon);
//初始化Thread對(duì)象
bool init_success = self->Init(runtime->GetThreadList(), runtime->GetJavaVM());
Runtime::Current()->EndThreadBirth();
if (!init_success) {
delete self;
return nullptr;
}
}
}
//設(shè)置創(chuàng)建String對(duì)象的entry point為StringFactory
self->InitStringEntryPoints();
self->SetState(kNative);
... //傳入的create_peer為false
{
ScopedObjectAccess soa(self);
Dbg::PostThreadStart(self);
}
return self;
}
2.2 Runtime::Start
bool Runtime::Start() {
..
Thread* self = Thread::Current();
self->TransitionFromRunnableToSuspended(kNative);
started_ = true;
// 創(chuàng)建JIT
if (jit_options_->UseJitCompilation() || jit_options_->GetSaveProfilingInfo()) {
std::string error_msg;
if (!IsZygote()) {
// If we are the zygote then we need to wait until after forking to create the code cache
// due to SELinux restrictions on r/w/x memory regions.
CreateJit();
} else if (jit_options_->UseJitCompilation()) {
if (!jit::Jit::LoadCompilerLibrary(&error_msg)) {
// Try to load compiler pre zygote to reduce PSS. b/27744947
LOG(WARNING) << "Failed to load JIT compiler with error " << error_msg;
}
}
}
...
{
ScopedTrace trace2("InitNativeMethods");
//初始化JniConstants的常量,JniConstants定義在/libnativehelper/include/native/JniConstants.h
//注冊runtime中的native method,主要對(duì)應(yīng)于Java層的java.lang,dalvik.system這些包下的類
InitNativeMethods();
}
//創(chuàng)建main_thread_group和system_thread_group
InitThreadGroups(self);
//創(chuàng)建一個(gè)java.lang.Thread對(duì)象,并將Thread.nativePeer變量設(shè)為ART中的Thread對(duì)象self
Thread::FinishStartup();
//調(diào)用ClassLoader.getSystemClassLoader創(chuàng)建系統(tǒng)ClassLoader
system_class_loader_ = CreateSystemClassLoader(this);
//如果當(dāng)前處于Zygote模式, 利用unshare,以及mount的SLAVE模式創(chuàng)建外部存儲(chǔ)文件系統(tǒng)
if (is_zygote_) {
if (!InitZygote()) {
return false;
}
} else {
if (is_native_bridge_loaded_) {
PreInitializeNativeBridge(".");
}
NativeBridgeAction action = force_native_bridge_
? NativeBridgeAction::kInitialize
: NativeBridgeAction::kUnload;
InitNonZygoteOrPostFork(self->GetJniEnv(),
/* is_system_server */ false,
action,
GetInstructionSetString(kRuntimeISA));
}
//啟動(dòng)java.lang.Daemon中定義的后臺(tái)線程
StartDaemonThreads();
{
ScopedObjectAccess soa(self);
self->GetJniEnv()->locals.AssertEmpty();
}
finished_starting_ = true;
//如果ProfilerOptions開啟且存在profile文件,打開profile文件
if (profiler_options_.IsEnabled() && !profile_output_filename_.empty()) {
int fd = open(profile_output_filename_.c_str(), O_RDWR|O_CREAT|O_EXCL, 0660);
if (fd >= 0) {
close(fd);
} else if (errno != EEXIST) {
LOG(WARNING) << "Failed to access the profile file. Profiler disabled.";
}
}
... //Trace相關(guān)
return true;
}
Runtime::Start
主要操作是:
- 如果當(dāng)前不是Zygote,則創(chuàng)建JIT
- 初始化
libnativehelper.so
中定義的JniConstants
,注冊java.lang
,dalvik.system
包下的本地方法 - 創(chuàng)建main_thread_group和system_thread_group
- 創(chuàng)建一個(gè)java.lang.Thread對(duì)象,并將Thread.nativePeer變量設(shè)為ART中的Thread對(duì)象self
- 調(diào)用ClassLoader.getSystemClassLoader創(chuàng)建系統(tǒng)ClassLoader
- 如果當(dāng)前處于Zygote模式, 利用unshare,以及mount的SLAVE模式創(chuàng)建外部存儲(chǔ)文件系統(tǒng);如果不是,則初始化native bridge
- 啟動(dòng)java.lang.Daemon中定義的后臺(tái)線程
- 判斷
ProfilerOptions
是否開啟,如果開啟且profile文件不為空,則打開profile文件(Profile文件是在7.0中跟JIT一起加入的, 主要為了提升運(yùn)行效率) - 查看
Trace
相關(guān)配置,如果不為空,則開啟Trace
三.總結(jié)
Java虛擬機(jī)有三個(gè)標(biāo)準(zhǔn)接口,只要實(shí)現(xiàn)這三個(gè)接口,就可以實(shí)現(xiàn)一個(gè)自定義的虛擬機(jī),這三個(gè)接口分別是:JNI_CreateJavaVM_, JNI_GetCreatedJavaVMs_, JNI_GetDefaultJavaVMInitArgs_
,這三個(gè)接口的具體實(shí)現(xiàn)都位于libart.so
動(dòng)態(tài)庫中,Zygote進(jìn)程是通過dlopen
打開libart.so
,之后通過dlsym
分別導(dǎo)出這三個(gè)接口,并調(diào)用JNI_CreateJavaVM_
創(chuàng)建虛擬機(jī)Runtime實(shí)例,并將Runtime實(shí)例保存在JavaVM
結(jié)構(gòu),JavaVM
代表的就是虛擬機(jī)執(zhí)行環(huán)境(在libart.so
中實(shí)際返回的是其子類JavaVMExt
).
需要留意的是,源碼的注釋中寫的很清楚,每一個(gè)進(jìn)程都必須有一個(gè)
JavaVM
,而每一個(gè)線程都有一個(gè)JNIEnv
JNI_CreateJavaVM_
創(chuàng)建虛擬機(jī)Runtime的過程可以總結(jié)為:
- 解析傳入的參數(shù),將參數(shù)以
key-value
的形式組合在一起 - 調(diào)用
Runtime::Create
創(chuàng)建Runtime實(shí)例,創(chuàng)建的過程中還會(huì)依次創(chuàng)建OatFileManager, Heap, LinearAlloc, JavaVMExt, Thread, ClassLinker
,同時(shí)初始化線程和ClassLinker - 調(diào)用
Runtime::Start
完成最后的初始化工作