概述
Zygote中文翻译为“受精卵”,正如其名,它主要用于孵化子进程。在Android系统中有以 下两种程序:
- java应用程序,主要基于ART虚拟机,所有的应用程序apk都属于这类
- native程序,也就是利用C或C++语言开发的程序,如bootanimation
所有的Java应用程序进程及系统服务SystemServer进程都由Zygote进程通过Linux的fork()函数孵化出来的,这也就是为什么把它称为Zygote的原因,因为他就像一个受精卵,孵化出无数子进程,而native程序则由Init程序创建启动。Zygote进程最初的名字不是“zygote”而 是“app_process”,这个名字是在Android.mk文件中定义的。
Zgyote是Android中的第一个art虚拟机,他通过socket的方式与其他进程进行通信,这里的“其他进程” 其实主要是系统进程——SystemServer。
Zygote是一个C/S模型,Zygote进程作为服务端,它主要负责创建Java虚拟机,加载系统资源,启 动SystemServer进程,以及在后续运行过程中启动普通的应用程序,其他进程作为客户端向它发 出“孵化”请求,而Zygote接收到这个请求后就“孵化”出一个新的进程。比如,当点击Launcher里 的 应用程序图标去启动一个新的应用程序进程时,这个请求会到达框架层的核心服务 ActivityManagerService中,当AMS收到这个请求后,它通过调用Process类发出一个“孵化”子进 程的Socket请求,而Zygote监听到这个请求后就立刻fork一个新的进程出来
入口
在“Android Framework—Init进程-14.启动服务”一文中已详细讲解过init进程是如何通过如下配置文件启动Zygote服务的
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
class main
priority -20
user root
group root readproc reserved_disk
socket zygote stream 660 root system
socket usap_pool_primary stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
onrestart restart wificond
writepid /dev/cpuset/foreground/tasks
/system/bin/app_process64为zygote服务的可执行文件,通过查看相关的mk文件查找zygote服务的入口文件为app_main.cpp
//frameworks/base/cmds/app_process/Android.mk
app_process_src_files := \
app_main.cpp \
LOCAL_MODULE:= app_process
LOCAL_MULTILIB := both
LOCAL_MODULE_STEM_32 := app_process32
LOCAL_MODULE_STEM_64 := app_process64
AppRuntime
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
在main函数中首先会创建AppRuntime,AppRuntime继承AndroidRuntime,AndroidRuntime是一个非常重要的类,那么什么是Runtime?归纳起来的意思就是,Runtime 是支撑程序运行的基础库,它是与语言绑定在一起的,比如:
- C Runtime:就是C standard lib, 也就是我们常说的libc。(有意思的是, Wiki会自动 将“C runtime” 重定向到 “C Standard Library”)
- Java Runtime: 同样,Wiki将其重定向到” Java Virtual Machine”, 这里当然包括Java 的支撑 类库(.jar)
- AndroidRuntime: 显而易见,就是为Android应用运行所需的运行时环境。这个环境包括以下东
东:
- Dalvik VM: Android的Java VM, 解释运行Dex格式Java程序。每个进程运行一个虚拟机(什 么叫运行虚拟机?说白了,就是一些C代码,不停的去解释Dex格式的二进制码(Bytecode),把 它们转成机器码(Machine code),然后执行,当然,现在大多数的Java 虚拟机都支持JIT, 也就是说,bytecode可能在运行前就已经被转换成机器码,从而大大提高了性能。过去一个普 遍的认识是Java 程序比C,C++等静态编译的语言慢,但随着JIT的介入和发展,这个已经完全 是过去时了,JIT的动态性运行允许虚拟机根据运行时环境,优化机器码的生成,在某些情况 下,Java甚至可以比C/C++跑得更快,同时又兼具平台无关的特性,这也是为什么Java如今如 此流行的原因之一吧)。
- Android的Java 类库, 大部分来自于 Apache Hamony, 开源的Java API 实现,如 java.lang, java.util, java.net. 但去除了AWT, Swing 等部件。
- JNI: C和Java互调的接口。
- Libc: Android也有很多C代码,自然少不了libc,注意的是,Android的libc叫 bionic C
因此AppRuntime在Android系统中就是应用程序运行的基础环境,AppRuntime自身还实现了如下内容
//cmds/app_process/app_main.cpp
class AppRuntime : public AndroidRuntime
{
public:
AppRuntime(char* argBlockStart, const size_t argBlockLength)
: AndroidRuntime(argBlockStart, argBlockLength)
, mClass(NULL)
{
}
void setClassNameAndArgs(const String8& className, int argc, char * const *argv) {
mClassName = className;
for (int i = 0; i < argc; ++i) {
mArgs.add(String8(argv[i]));
}
}
virtual void onVmCreated(JNIEnv* env)
{
if (mClassName.isEmpty()) {
return; // Zygote. Nothing to do here.
}
/*
* This is a little awkward because the JNI FindClass call uses the
* class loader associated with the native method we're executing in.
* If called in onStarted (from RuntimeInit.finishInit because we're
* launching "am", for example), FindClass would see that we're calling
* from a boot class' native method, and so wouldn't look for the class
* we're trying to look up in CLASSPATH. Unfortunately it needs to,
* because the "am" classes are not boot classes.
*
* The easiest fix is to call FindClass here, early on before we start
* executing boot class Java code and thereby deny ourselves access to
* non-boot classes.
*/
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));
}
virtual void onStarted()
{
sp<ProcessState> proc = ProcessState::self();
ALOGV("App process: starting thread pool.\n");
proc->startThreadPool();
AndroidRuntime* ar = AndroidRuntime::getRuntime();
ar->callMain(mClassName, mClass, mArgs);
IPCThreadState::self()->stopProcess();
hardware::IPCThreadState::self()->stopProcess();
}
virtual void onZygoteInit()
{
sp<ProcessState> proc = ProcessState::self();
ALOGV("App process: starting thread pool.\n");
proc->startThreadPool();
}
virtual void onExit(int code)
{
if (mClassName.isEmpty()) {
// if zygote
IPCThreadState::self()->stopProcess();
hardware::IPCThreadState::self()->stopProcess();
}
AndroidRuntime::onExit(code);
}
String8 mClassName;
Vector<String8> mArgs;
jclass mClass;
};
- mClassName:指定要启动的java类名
- mClass:如果mClassName存在,在onVmCreated中会找到mClassName对应的class
- mArgs:启动mClassName时传递的启动参数
其它实现方法在后续的分析中会被调用到,然后再做进一步分析。
static AndroidRuntime* gCurRuntime = NULL;
AndroidRuntime::AndroidRuntime(char* argBlockStart, const size_t argBlockLength) :
mExitWithoutCleanup(false),
mArgBlockStart(argBlockStart),
mArgBlockLength(argBlockLength)
{
SkGraphics::Init();
// Pre-allocate enough space to hold a fair number of options.
mOptions.setCapacity(20);
assert(gCurRuntime == NULL); // one per process
gCurRuntime = this;
}
在AndroidRuntime的构造函数中会将AppRuntime实例赋值给gCurRuntime,gCurRuntime在代码中作为一个全局单例对象使用,它代表虚拟机实例,因此一个进程中只会有一个虚拟机实例。
main
// 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 : Start the 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.
//
// As an exception to the above rule, anything in "spaced commands"
// goes to the vm even though it has a space in it.
这段注释说明了/system/bin/app_process64这个可执行程序的用法
app_process [java-options] cmd-dir start-class-name [options]
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
- java-options:在'--'开头的参数或者第一个非'-'参数之前的字符串都是需要传递给虚拟机的java选项(Everything up to '--' or first non '-' arg goes to the vm)
- cmd-dir:在java-options后面的第一个参数为可执行程序的工作根目录(After the parent dir)
- start-class-name:指定启动的类名
- options:其它选项
- --zygote : 启动zygote进程
- --start-system-server : 启动system server进程
- --application : 启动应用程序进程
- --nice-name : 指定进程名称
const char* spaced_commands[] = { "-cp", "-classpath" };
// Allow "spaced commands" to be succeeded by exactly 1 argument (regardless of -s).
bool known_command = false;
int i;
for (i = 0; i < argc; i++) {
if (known_command == true) {
runtime.addOption(strdup(argv[i]));
// The static analyzer gets upset that we don't ever free the above
// string. Since the allocation is from main, leaking it doesn't seem
// problematic. NOLINTNEXTLINE
ALOGV("app_process main add known option '%s'", argv[i]);
known_command = false;
continue;
}
for (int j = 0;
j < static_cast<int>(sizeof(spaced_commands) / sizeof(spaced_commands[0]));
++j) {
if (strcmp(argv[i], spaced_commands[j]) == 0) {
known_command = true;
ALOGV("app_process main found known command '%s'", argv[i]);
}
}
if (argv[i][0] != '-') {
break;
}
if (argv[i][1] == '-' && argv[i][2] == 0) {
++i; // Skip --.
break;
}
runtime.addOption(strdup(argv[i]));
// The static analyzer gets upset that we don't ever free the above
// string. Since the allocation is from main, leaking it doesn't seem
// problematic. NOLINTNEXTLINE
ALOGV("app_process main add option '%s'", argv[i]);
}
有了上面的说明后,这段就比较好理解了:它其实就是解析出参数中的java-options,然后调用addOption添加到虚拟机中
void AndroidRuntime::addOption(const char* optionString, void* extraInfo)
{
JavaVMOption opt;
opt.optionString = optionString;
opt.extraInfo = extraInfo;
mOptions.add(opt);
}
紧接着继续解析参数,将options内容都解析到如下局部变量中
// 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;
}
}
根据是否有className设置向args中添加不同的启动参数,值得注意的是如果className存在好会调用setClassNameAndArgs将ClassName和args保存到runtime中
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);
if (!LOG_NDEBUG) {
String8 restOfArgs;
char* const* argv_new = argv + i;
int argc_new = argc - i;
for (int k = 0; k < argc_new; ++k) {
restOfArgs.append(""");
restOfArgs.append(argv_new[k]);
restOfArgs.append("" ");
}
ALOGV("Class name = %s, args = %s", className.string(), restOfArgs.string());
}
} 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(), true /* setProcName */);
}
main方法会完成如下进程的启动
- zygote进程启动
- 指定className启动
他们都是通过调用AndroidRuntime的start方法进行启动
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.");
}
AndroidRuntime.start
在start方法的最终目的是调用ZygoteInit的main方法或启动指定的className,但是在此之前会进行如下初始化工作:
- 创建虚拟机
- 注册JNI函数,因为zygote启动后会进入Android的Java世界,后续的Java应用程序都会通过JNI调用c/c++层
- 最后通过JNI调用到Zygote的Java世界
/*static*/ JavaVM* AndroidRuntime::mJavaVM = NULL;
/* start the virtual machine */
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
if (startVm(&mJavaVM, &env, zygote) != 0) {
return;
}
调用startVm创建虚拟机,创建的虚拟机实例对象为mJavaVM,以及JNIEnv指针env。
onVmCreated(env);
调用onVmCreated,AppRuntime中覆盖实现了此方法
- zygote进程:什么都不做
- 指定className:会找到className对应的class
/*
* Register android functions.
*/
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
调用startReg注册android系统的所有JNI函数
static const RegJNIRec gRegJNI[] = {
REG_JNI(register_com_android_internal_os_RuntimeInit),
REG_JNI(register_com_android_internal_os_ZygoteInit_nativeZygoteInit),
REG_JNI(register_android_os_SystemClock),
REG_JNI(register_android_util_EventLog),
....
REG_JNI(register_com_android_internal_os_AtomicDirectory),
REG_JNI(register_com_android_internal_os_FuseAppLoop),
};
static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)
{
for (size_t i = 0; i < count; i++) {
if (array[i].mProc(env) < 0) {
#ifndef NDEBUG
ALOGD("----------!!! %s failed to load\n", array[i].mName);
#endif
return -1;
}
}
return 0;
}
/*static*/ int AndroidRuntime::startReg(JNIEnv* env)
{
...
if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
env->PopLocalFrame(NULL);
return -1;
}
...
return 0;
}
这里会循环调用gRegJNI数组中定义的mProc函数,mProc实际就是REG_JNI宏中定义的方法名
int register_com_android_internal_os_RuntimeInit(JNIEnv* env)
{
const JNINativeMethod methods[] = {
{ "nativeFinishInit", "()V",
(void*) com_android_internal_os_RuntimeInit_nativeFinishInit },
{ "nativeSetExitWithoutCleanup", "(Z)V",
(void*) com_android_internal_os_RuntimeInit_nativeSetExitWithoutCleanup },
};
return jniRegisterNativeMethods(env, "com/android/internal/os/RuntimeInit",
methods, NELEM(methods));
}
int register_com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env)
{
const JNINativeMethod methods[] = {
{ "nativeZygoteInit", "()V",
(void*) com_android_internal_os_ZygoteInit_nativeZygoteInit },
};
return jniRegisterNativeMethods(env, "com/android/internal/os/ZygoteInit",
methods, NELEM(methods));
}
JNI方法又会调用jniRegisterNativeMethods
MODULE_API int jniRegisterNativeMethods(C_JNIEnv* env, const char* className,
const JNINativeMethod* gMethods, int numMethods)
{
JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
ALOGV("Registering %s's %d native methods...", className, numMethods);
scoped_local_ref<jclass> c(env, findClass(env, className));
ALOG_ALWAYS_FATAL_IF(c.get() == NULL,
"Native registration unable to find class '%s'; aborting...",
className);
int result = e->RegisterNatives(c.get(), gMethods, numMethods);
ALOG_ALWAYS_FATAL_IF(result < 0, "RegisterNatives failed for '%s'; aborting...",
className);
return 0;
}
最后所有的JNI方法都会被注册到JNIEnv中,而这个JNIEnv对象就是前面创建虚拟机时所创建的。
/*
* We want to call main() with a String array with arguments in it.
* At present we have two arguments, the class name and an option string.
* Create an array to hold them.
*/
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);
}
这个代码块是为后续启动zygote进程或者指定的className准备启动参数:
- 创建strArray数组并分配空间
- 如果className存在,则将其放在数组的第 0 位置
- 最后将options中所有参数依次放入strArray数组
char* slashClassName = toSlashClassName(className != NULL ? 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 {
env->CallStaticVoidMethod(startClass, startMeth, strArray);
#if 0
if (env->ExceptionCheck())
threadExitUncaughtException(env);
#endif
}
}
最后会找到com.android.internal.os.ZygoteInit或com.android.internal.os.RuntimeInit的main方法进行启动,并传递启动参数strArray,这样一来就进入到Java世界了。
startVm创建虚拟机
/*static*/ JavaVM* AndroidRuntime::mJavaVM = NULL;
/* start the virtual machine */
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
if (startVm(&mJavaVM, &env, zygote) != 0) {
return;
}
这里我们重点分析一下虚拟机的创建,上面是调用虚拟机创建的相关代码。
//libnativehelper/JniInvocation.cpp
bool JniInvocationImpl::Init(const char* library) {
#ifdef __ANDROID__
char buffer[PROP_VALUE_MAX];
#else
char* buffer = NULL;
#endif
library = GetLibrary(library, buffer);
handle_ = OpenLibrary(library);
if (handle_ == NULL) {
if (strcmp(library, kLibraryFallback) == 0) {
// Nothing else to try.
ALOGE("Failed to dlopen %s: %s", library, GetError().c_str());
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, GetError().c_str());
library = kLibraryFallback;
handle_ = OpenLibrary(library);
if (handle_ == NULL) {
ALOGE("Failed to dlopen %s: %s", library, GetError().c_str());
return false;
}
}
if (!FindSymbol(reinterpret_cast<FUNC_POINTER*>(&JNI_GetDefaultJavaVMInitArgs_),
"JNI_GetDefaultJavaVMInitArgs")) {
return false;
}
if (!FindSymbol(reinterpret_cast<FUNC_POINTER*>(&JNI_CreateJavaVM_),
"JNI_CreateJavaVM")) {
return false;
}
if (!FindSymbol(reinterpret_cast<FUNC_POINTER*>(&JNI_GetCreatedJavaVMs_),
"JNI_GetCreatedJavaVMs")) {
return false;
}
return true;
}
jni_invocation.Init方法做了如下工作:
- 在app_process进程中动态加载动态库libart.so,libart.so是Android Art虚拟机库
- GetLibrary:得到动态库名
- OpenLibrary:打开动态库返回动态库句柄
- 找到动态库中下面函数地址,创建虚拟机时会使用到这些函数
- 名为JNI_GetDefaultJavaVMInitArgs的函数地址,保存到JNI_GetDefaultJavaVMInitArgs_中
- 名为JNI_CreateJavaVM的函数地址,保存到JNI_CreateJavaVM_中
- 名为JNI_GetCreatedJavaVMs_的函数地址,保存到JNI_GetCreatedJavaVMs中
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote)
{
//startVM的前半部分是在处理虚拟机的启动参数,处理完配置参数后,会调用libart.so提供
的一个接口:JNI_CreateJavaVM函数
if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
ALOGE("JNI_CreateJavaVM failed\n");
return -1;
}
}
前面大部分都是处理虚拟机的启动参数以及属性设置,startVm最核心的代码就是调用JNI_CreateJavaVM方法,JNI_CreateJavaVM调用的就是前面找到的函数地址,其实现源码位于art/runtime/jni/java_vm_ext.cc中
//art/runtime/jni/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);
if (JavaVMExt::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;
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();
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对象,runtime负责提供art虚拟机的运行时 环境
bool Runtime::Create(RuntimeArgumentMap&& runtime_options) {
// TODO: acquire a static mutex on Runtime to avoid racing.
if (Runtime::instance_ != nullptr) {
return false;
}
instance_ = new Runtime;
Locks::SetClientCallback(IsSafeToCallAbort);
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;
}
然后调用其init方法来初始化虚拟机
bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) {
...
//创建堆管理对象
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),
...
)
//创建java虚拟机对象
std::string error_msg;
java_vm_ = JavaVMExt::Create(this, runtime_options, &error_msg);
if (java_vm_.get() == nullptr) {
LOG(ERROR) << "Could not initialize JavaVMExt: " << error_msg;
return false;
}
//连接主线程
// 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);
//创建类连接器
if (UNLIKELY(IsAotCompiler())) {
class_linker_ = new AotClassLinker(intern_table_);
} else {
class_linker_ = new ClassLinker(
intern_table_,
runtime_options.GetOrDefault(Opt::FastClassNotFoundException));
}
if (GetHeap()->HasBootImageSpace()) {
//初始化类连接器
bool result = class_linker_->InitFromBootImage(&error_msg);
if (!result) {
LOG(ERROR) << "Could not initialize from image: " << error_msg;
return false;
}
}
}
- new gc::heap(),创建Heap对象,这是虚拟机管理对内存的起点。
- new JavaVmExt(),创建Java虚拟机实例。
- Thread::attach(),attach主线程
- 创建ClassLinker
- 初始化ClassLinker,成功attach到runtime环境后,创建ClassLinker实例负责管理java class
到这里,虚拟机的创建和初始化就完成了
Runtime* runtime = Runtime::Current();
*p_env = Thread::Current()->GetJniEnv();
*p_vm = runtime->GetJavaVM();
虚拟机的创建完成后调用Current方法返回前面创建的Runtime单例对象,最后返回JavaVM虚拟机对象和当前线程的JNIEnv对象,注册JNI函数时会使用到JNIEnv(前面已经讲解过),值得注意的是:
- JavaVM每个进程只有一个
- JNIEnv每个线程有一个
官方注释如下
/*
* 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;
}