您的位置:首页 > 移动开发 > Android开发

Android5.1.1源码 - 虚拟机的创建

2015-11-01 00:00 423 查看
摘要: Android5.1.1源码 - 虚拟机的创建

Android5.1.1源码 - 虚拟机的创建

@(Android研究)[Android|源码|虚拟机]

[TOC]

虚拟机启动时的函数调用路径:

app_main.cc - main
|-- AndroidRuntime::start
|-- AndroidRuntime::startVm
|-- JNI_CreateJavaVM

当init进程启动zygote进程时会创建虚拟机,下是zygote代码的main函数,本文从这里开始分析虚拟机如何创建,这个函数在文件"frameworks/base/cmds/app_process/app_main.cpp"中,下面是它的源码:

int main(int argc, char* const argv[])
{
......

AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
// 处理命令行参数
// 忽略 argv[0]
argc--;
argv++;

// Everything up to '--' or first non '-' arg goes to the vm.
//
// The first argument after the VM args is the "parent dir", which
// is currently unused.
//
// After the parent dir, we expect one or more the following internal
// arguments :
//
// --zygote : Start in zygote mode
// --start-system-server : 启动系统服务
// --application : Start in application (stand alone, non zygote) mode.
// --nice-name : The nice name for this process.
//
// For non zygote starts, these arguments will be followed by
// the main class name. All remaining arguments are passed to
// the main method of this class.
//
// For zygote starts, all remaining arguments are passed to the zygote.
// main function.
//
// Note that we must copy argument string values since we will rewrite the
// entire argument block when we apply the nice name to argv0.

int i;
for (i = 0; i < argc; i++) {
if (argv[i][0] != '-') {
break;
}
if (argv[i][1] == '-' && argv[i][2] == 0) {
++i; // Skip --.
break;
}
runtime.addOption(strdup(argv[i]));
}

// Parse runtime arguments.  Stop at first unrecognized option.
bool zygote = false;
bool startSystemServer = false;
bool application = false;
String8 niceName;
String8 className;

++i;  // Skip unused "parent dir" argument.
while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) {
zygote = true;
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true;
} else if (strcmp(arg, "--application") == 0) {
application = true;
} else if (strncmp(arg, "--nice-name=", 12) == 0) {
niceName.setTo(arg + 12);
} else if (strncmp(arg, "--", 2) != 0) {
className.setTo(arg);
break;
} else {
--i;
break;
}
}

Vector<String8> args;
if (!className.isEmpty()) {
// We're not in zygote mode, the only argument we need to pass
// to RuntimeInit is the application argument.
//
// The Remainder of args get passed to startup class main(). Make
// copies of them before we overwrite them with the process name.
args.add(application ? String8("application") : String8("tool"));
runtime.setClassNameAndArgs(className, argc - i, argv + i);
} else {
// We're in zygote mode.
maybeCreateDalvikCache();

if (startSystemServer) {
args.add(String8("start-system-server"));
}

char prop[PROP_VALUE_MAX];
if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
ABI_LIST_PROPERTY);
return 11;
}

String8 abiFlag("--abi-list=");
abiFlag.append(prop);
args.add(abiFlag);

// In zygote mode, pass all remaining arguments to the zygote
// main() method.
for (; i < argc; ++i) {
args.add(String8(argv[i]));
}
}

if (!niceName.isEmpty()) {
runtime.setArgv0(niceName.string());
set_process_name(niceName.string());
}

if (zygote) {
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;
}
}

**runtime.start(...)**语句启动了Android运行时,在启动Android运行时的同时会启动虚拟机。main函数中的局部变量runtime是AppRuntime类的对象,这个类的代码定义在文件"frameworks/base/cmds/app_process/app_main.cpp"中,AppRuntime类继承了AndroidRuntime类,而start函数就是AndroidRuntime类的成员函数。

AndroidRuntime类定义在文件"frameworks/base/core/jni/AndroidRuntime.cpp"中,下面是AndroidRuntime::start函数的代码:

/*
* 启动Android运行时。它启动虚拟机并调用通过"className"参数所指定的类名中
* 的"static void main(String[] args)"方法。
*
* 向main函数传入两个参数:类名和被指定的选项字符串。
*/
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
ALOGD(">>>>>> START %s uid %d <<<<<<\n",
className != NULL ? className : "(unknown)", getuid());

......

/* 启动虚拟机。 */
JniInvocation jni_invocation;
jni_invocation.Init(NULL);  // 初始化JNI API接口
JNIEnv* env;
if (startVm(&mJavaVM, &env, zygote) != 0) {
return;
}
onVmCreated(env);  // 在zygote中这个函数什么都不做。

/*
* Register android functions.
*/
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}

/*
* 我们要调用main(),将一个字符串数组当做参数传入。
* 目前,我们有两个参数,类名和一个选项字符串。
* 创建一个数组来保存它们。
*/
jclass stringClass;
jobjectArray strArray;
jstring classNameStr;

stringClass = env->FindClass("java/lang/String");
assert(stringClass != NULL);
strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
assert(strArray != NULL);
classNameStr = env->NewStringUTF(className);
assert(classNameStr != NULL);
env->SetObjectArrayElement(strArray, 0, classNameStr);

for (size_t i = 0; i < options.size(); ++i) {
jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
assert(optionsStr != NULL);
env->SetObjectArrayElement(strArray, i + 1, optionsStr);
}

/*
* 启动Start VM。这个线程成为VM的主线程,直到VM结束前不会返回。
*
* 对于zygote而言除非设备关机否则这个线程是不会退出的,将zygote
* 比作服务端,这个服务端会一直等待并处理各种客户端的请求。
*/
char* slashClassName = toSlashClassName(className);
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
if (startMeth == NULL) {
ALOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
// 调用Java方法。
env->CallStaticVoidMethod(startClass, startMeth, strArray);

#if 0
if (env->ExceptionCheck())
threadExitUncaughtException(env);
#endif
}
}
free(slashClassName);

ALOGD("Shutting down VM\n");
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");
}

这个函数主要做了下面三件事情:

调用**jni_invocation.Init(NULL);**语句初始化JNI API。

调用startVm函数创建了虚拟机。

env->CallStaticVoidMethod语句调用类的main方法。

这个函数中调用了**onVmCreated(env);**语句,对于zygote来说,这个函数不做任何事情。

jni_invocation虽然是AndroidRuntime::start函数的局部变量,但是对于zygote而言除非设备关机否则是不会退出AndroidRuntime::start函数的。对于普通APP,除非APP结束否则也不会退出AndroidRuntime::start函数。在另一篇分析zygote启动过程的文章中会说明原因。

JniInvocation::Init这个函数用于初始化JNI调用,这个函数在文件libnativehelper/JniInvocation.cpp中,下面是这个函数的代码:

/**
* 初始化JNI调用API。参数library应当传入可供dlopen打开的有效的共享库,
* 这个共享库提供一个JNI调用实现,或者参数library被传入null则将通过
* persist.sys.dalvik.vm.lib使用默认值。
*/
bool JniInvocation::Init(const char* library) {
#ifdef HAVE_ANDROID_OS
char buffer[PROPERTY_VALUE_MAX];
#else
char* buffer = NULL;
#endif
// 获得共享库名。
library = GetLibrary(library, buffer);

// 加载这个共享库。
handle_ = dlopen(library, RTLD_NOW);
if (handle_ == NULL) {
if (strcmp(library, kLibraryFallback) == 0) {
// Nothing else to try.
ALOGE("Failed to dlopen %s: %s", library, dlerror());
return false;
}
// Note that this is enough to get something like the zygote
// running, we can't property_set here to fix this for the future
// because we are root and not the system user. See
// RuntimeInit.commonInit for where we fix up the property to
// avoid future fallbacks. http://b/11463182 ALOGW("Falling back from %s to %s after dlopen error: %s",
library, kLibraryFallback, dlerror());
library = kLibraryFallback;
handle_ = dlopen(library, RTLD_NOW);
if (handle_ == NULL) {
ALOGE("Failed to dlopen %s: %s", library, dlerror());
return false;
}
}

// 找到符号JNI_GetDefaultJavaVMInitArgs。
if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetDefaultJavaVMInitArgs_),
"JNI_GetDefaultJavaVMInitArgs")) {
return false;
}

// 找到符号JNI_CreateJavaVM。
if (!FindSymbol(reinterpret_cast<void**>(&JNI_CreateJavaVM_),
"JNI_CreateJavaVM")) {
return false;
}

// 找到符号JNI_GetCreatedJavaVMs。
if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetCreatedJavaVMs_),
"JNI_GetCreatedJavaVMs")) {
return false;
}
return true;
}

这个函数做了下面两件事情:

获得包含JNI接口的共享库名。

加载这个共享库。

从这个共享库中获得了三个符号的地址:JNI_GetDefaultJavaVMInitArgs、JNI_CreateJavaVM和JNI_GetCreatedJavaVMs。

JniInvocation类中的成员变量handle_保存了共享库的句柄,成员函数JNI_GetDefaultJavaVMInitArgs_、*JNI_CreateJavaVM_和JNI_GetCreatedJavaVMs_*均保存了从共享库中获得的函数地址。

JniInvocation::Init调用了JniInvocation::GetLibrary函数获得了共享库名,这个共享库中有JNI函数的实现,这个函数在文件libnativehelper/JniInvocation.cpp中,下面是它的代码:

#ifdef HAVE_ANDROID_OS
static const char* kLibrarySystemProperty = "persist.sys.dalvik.vm.lib.2";
static const char* kDebuggableSystemProperty = "ro.debuggable";
static const char* kDebuggableFallback = "0";  // Not debuggable.
#endif
static const char* kLibraryFallback = "libart.so";

const char* JniInvocation::GetLibrary(const char* library, char* buffer) {
#ifdef HAVE_ANDROID_OS
const char* default_library;

char debuggable[PROPERTY_VALUE_MAX];
property_get(kDebuggableSystemProperty, debuggable, kDebuggableFallback);

if (strcmp(debuggable, "1") != 0) {
// Not a debuggable build.
// Do not allow arbitrary library.  This
// will also ignore the default library, but initialize to fallback
// for cleanliness.
library = kLibraryFallback;
default_library = kLibraryFallback;
} else {
// Debuggable build.
// Accept the library parameter. For the case it is NULL, load the default
// library from the system property.
if (buffer != NULL) {
property_get(kLibrarySystemProperty, buffer, kLibraryFallback);
default_library = buffer;
} else {
// 如果没有指定缓冲区,使用备用的默认值。
default_library = kLibraryFallback;
}
}
#else
UNUSED(buffer);
const char* default_library = kLibraryFallback;
#endif
if (library == NULL) {
library = default_library;
}

return library;
}

可以发现JniInvocation::GetLibrary函数中默认的库是kLibraryFallback,而这个变量的值为libart.so,这个函数的返回值与kLibrarySystemProperty变量也有关系,而这个变量中保存的属性对应的值通常为libart.so。所以在这里我武断的认定这个函数的返回值总为libart.so以便后面分析。

对AndroidRuntime::start函数中所执行**jni_invocation.Init(NULL);**语句做一个
总结


它加载了libart.so。

jni_invocation对象中保存了libart.so的句柄。

jni_invocation对象中保存了JNI_GetDefaultJavaVMInitArgs、JNI_CreateJavaVM和JNI_GetCreatedJavaVMs这三个函数的地址。

继续对AndroidRuntime::start函数进行分析,在执行完**jni_invocation.Init(NULL);**语句后紧接着调用了startVm函数,这个函数启动了虚拟机。这个函数在文件frameworks/base/core/jni/AndroidRuntime.cpp中,下面是它的源码:

/*
* Start the Dalvik Virtual Machine.
* (PS:这里翻译过来是:启动Dalvik虚拟机,我认为是这只不过是注释内容还未被修改,而实际上启动的已经不是dalvik虚拟机了)
*
* Various arguments, most determined by system properties, are passed in.
* The "mOptions" vector is updated.
*
* CAUTION: when adding options in here, be careful not to put the
* char buffer inside a nested scope.  Adding the buffer to the
* options using mOptions.add() does not copy the buffer, so if the
* buffer goes out of scope the option may be overwritten.  It's best
* to put the buffer at the top of the function so that it is more
* unlikely that someone will surround it in a scope at a later time
* and thus introduce a bug.
*
* Returns 0 on success.
*/
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote)
{
int result = -1;
JavaVMInitArgs initArgs;

......

// checkjni属性。
bool checkJni = false;
property_get("dalvik.vm.checkjni", propBuf, "");
if (strcmp(propBuf, "true") == 0) {
checkJni = true;
} else if (strcmp(propBuf, "false") != 0) {
/* 属性即不为真也不为假;转到内核参数。 */
property_get("ro.kernel.android.checkjni", propBuf, "");
if (propBuf[0] == '1') {
checkJni = true;
}
}
ALOGD("CheckJNI is %s\n", checkJni ? "ON" : "OFF");
if (checkJni) {
/* extended JNI checking */
addOption("-Xcheck:jni");

/* 设置JNI全局引用上限 */
addOption("-Xjnigreflimit:2000");

/* with -Xcheck:jni, 这提供JNI函数调用跟踪 */
//addOption("-verbose:jni");
}

// 根据属性获得虚拟机的执行模式。
property_get("dalvik.vm.execution-mode", propBuf, "");
if (strcmp(propBuf, "int:portable") == 0) {
executionMode = kEMIntPortable;
} else if (strcmp(propBuf, "int:fast") == 0) {
executionMode = kEMIntFast;
} else if (strcmp(propBuf, "int:jit") == 0) {
executionMode = kEMJitCompiler;
}

......

/* Force interpreter-only mode for selected opcodes. Eg "1-0a,3c,f1-ff" */
parseRuntimeOption("dalvik.vm.jit.op", jitOpBuf, "-Xjitop:");

/* Force interpreter-only mode for selected methods */
parseRuntimeOption("dalvik.vm.jit.method", jitMethodBuf, "-Xjitmethod:");

// 向mOptions中添加执行模式。
if (executionMode == kEMIntPortable) {
addOption("-Xint:portable");
} else if (executionMode == kEMIntFast) {
addOption("-Xint:fast");
} else if (executionMode == kEMJitCompiler) {
addOption("-Xint:jit");
}

// libart容许libdvm flags,但反过来不行,所以仅libart的情况下才传入一些选项。
property_get("persist.sys.dalvik.vm.lib.2", dalvikVmLibBuf, "libart.so");
bool libart = (strncmp(dalvikVmLibBuf, "libart", 6) == 0);

if (libart) {
......
}

......

initArgs.version = JNI_VERSION_1_4;
initArgs.options = mOptions.editArray();
initArgs.nOptions = mOptions.size();
initArgs.ignoreUnrecognized = JNI_FALSE;

/*
* 初始化VM。
*
* JavaVM*作用于每个进程,JNIEnv*作用于每个线程(The JavaVM* is essentially per-process, and the JNIEnv* is per-thread.)。
*
* 如果这个调用成功,则VM就绪,and we can start issuing
* JNI calls.
*/
if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
ALOGE("JNI_CreateJavaVM failed\n");
goto bail;
}

result = 0;

bail:
return result;
}

AndroidRuntime::startVm函数主要做了两件事情:

解析系统属性,并将系统属性添加到mOptions中,然后将mOptions封装到initArgs中。

调用JNI_CreateJavaVM函数创建一个Java虚拟机。

系统属性主要通过property_get函数获得,这个函数会去系统属性文件中读取属性。

当要添加一个新的选项时会调用AndroidRuntime::addOption函数,它向mOptions中添加一个JavaVMOption对象,这个函数在frameworks/base/core/jni/AndroidRuntime.cpp文件中,下面是它的源码:

void addOption(const char* optionString, void* extra_info = NULL);

void AndroidRuntime::addOption(const char* optionString, void* extraInfo)
{
JavaVMOption opt;
opt.optionString = optionString;
opt.extraInfo = extraInfo;
mOptions.add(opt);
}

下面开始分析JNI_CreateJavaVM函数,这个定义在libnativehelper/JniInvocation.cpp文件中,下面是它的源码:

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);
}

JniInvocation::GetJniInvocation()函数获得的是JniInvocation类的实例,JniInvocation::GetJniInvocation().JNI_CreateJavaVM调用的是JniInvocation类中非静态成员函数JNI_CreateJavaVM,下面是这个成员函数的源码:

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类中的非静态成员变量,它指向的是前面所加载的libart.so中的JNI_CreateJavaVM函数,这个成员变量在JniInvocation::Init函数中被赋值。

libart.so中的JNI_CreateJavaVM函数创建了虚拟机,它的源码art/runtime/jni_internal.cc文件中,下面是这个函数的源码:

/**
* 创建虚拟机。
* 参数p_vm和p_env是输出参数。
* 参数vm_args是输入参数,这个参数保存的是虚拟机创建过程中需要用到的选项。
*/
extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
const JavaVMInitArgs* args = static_cast<JavaVMInitArgs*>(vm_args);

// 检查Jni版本。
if (IsBadJniVersion(args->version)) {
LOG(ERROR) << "Bad JNI version passed to CreateJavaVM: " << args->version;
return JNI_EVERSION;
}

// 将所有的虚拟机选项均保存到options中。
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;
if (!Runtime::Create(options, ignore_unrecognized)) {
return JNI_ERR;
}

// 启动运行时环境。
Runtime* runtime = Runtime::Current();
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 = runtime->GetJavaVM();
return JNI_OK;
}

JNI_CreateJavaVM函数主要做了两件事情:

Runtime::Create语句创建运行时环境。

**runtime->Start();**语句启动运行时环境。

RuntimeOptions类型的定义在文件art/runtime/runtime.h中:

typedef std::vector<std::pair<std::string, const void*>> RuntimeOptions;

Runtime::Create函数是一个静态函数在文件art/runtime/runtime.cc中,下面是它的源码:

bool Runtime::Create(const RuntimeOptions& options, bool ignore_unrecognized) {
// TODO: acquire a static mutex on Runtime to avoid racing.
if (Runtime::instance_ != NULL) {
return false;
}
InitLogging(NULL);  // Calls Locks::Init() as a side effect.
instance_ = new Runtime;
if (!instance_->Init(options, ignore_unrecognized)) {
delete instance_;
instance_ = NULL;
return false;
}
return true;
}

通过分析上面的代码可以发现Runtime类被设计为单例模式,单例对象保存在instance_中,然后又调用了Init函数。

Runtime::Init函数在文件art/runtime/runtime.cc中,下面是它的源码:

bool Runtime::Init(const RuntimeOptions& raw_options, bool ignore_unrecognized) {
CHECK_EQ(sysconf(_SC_PAGE_SIZE), kPageSize);

MemMap::Init();

std::unique_ptr<ParsedOptions> options(ParsedOptions::Create(raw_options, ignore_unrecognized));

......

java_vm_ = new JavaVMExt(this, options.get());

Thread::Startup();

// 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);

......

VLOG(startup) << "Runtime::Init exiting";
return true;
}

这个函数中的new JavaVMExt语句创建了JavaVMExt对象,一个虚拟机有且仅有一个JavaVMExt对象,JavaVMExt类型继承了JavaVM类型,可以去查看"art/runtime/jni_internal.h"文件。Thread::Attach函数将虚拟机附加到主线程上。

Thread::Attach函数的源码在文件"art/runtime/thread.cc"文件中,下面是它的源码:

Thread* Thread::Attach(const char* thread_name, bool as_daemon, jobject thread_group,
bool create_peer) {
Thread* self;
Runtime* runtime = Runtime::Current();
if (runtime == nullptr) {
LOG(ERROR) << "Thread attaching to non-existent runtime: " << thread_name;
return nullptr;
}
{
MutexLock mu(nullptr, *Locks::runtime_shutdown_lock_);
if (runtime->IsShuttingDownLocked()) {
......
} else {
Runtime::Current()->StartThreadBirth();
self = new Thread(as_daemon);
self->Init(runtime->GetThreadList(), runtime->GetJavaVM());
Runtime::Current()->EndThreadBirth();
}
}

......
}

在这个函数中创建了Thread对象,然后调用了Thread::Init函数,在这个函数中创建了当前线程的JNIEnv。

Thread::Init函数的源码在文件"art/runtime/thread.cc"文件中,下面是这个函数的源码:

void Thread::Init(ThreadList* thread_list, JavaVMExt* java_vm) {
......

tlsPtr_.jni_env = new JNIEnvExt(this, java_vm);

......
}

这个函数中创建了JNIEnvExt对象。JNIEnvExt类型继承了JNIEnv类型,可以去"art/runtime/jni_internal.h"文件中查看。

现在回到JNI_CreateJavaVM函数中,Runtime::Create函数执行完后,将执行Runtime::Start函数启动Android运行时,然会调用这两行语句返回创建的Java虚拟机对象和当前线程的JNI环境:

*p_env = Thread::Current()->GetJniEnv();
*p_vm = runtime->GetJavaVM();

Thread::Current函数获得当前线程的对象。

Tread::GetJniEnv()获得当前线程的JNI环境,这个函数的定义在文件"art/runtime/thread-inl.h"中,下面是它的源码:

// JNI methods
JNIEnvExt* GetJniEnv() const {
return tlsPtr_.jni_env;
}

Runtime::GetJavaVM()函数获得的是Java虚拟机对象,它的定义在文件"art/runtime/runtime.h"中,下面是它的源码:

JavaVMExt* GetJavaVM() const {
return java_vm_;
}

执行完JNI_CreateJavaVM函数后返回到startVM函数中。

执行完startVM成功启动虚拟机后,将会通过env->CallStaticVoidMethod语句调用"com.android.internal.os.ZygoteInit"这个Java类的main方法,这个Java方法将会启动zygote服务。

关于如何启动zygote服务将另写一篇文章分析。

至此Android5.1源码虚拟机启动过程分析完毕。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Android 源码 虚拟机