Android系统的第一个进程是init,init通过解析init.rc脚本来启动关键的守护进程和各种系统服务--其中包括zygote这个应用程序的孵化器。
system/core/rootdir/init.zygote64.rc(这个文件会被import进init.rc中)
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
class main
socket zygote 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
writepid /dev/cpuset/foreground/tasks
进程app_process是zygote的载体,app_process启动后,会调用AndroidRuntime的start方法,对应源码:
frameworks/base/cmds/app_process/app_main.cpp
int main(int argc, char* const argv[])
{
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();
return 10;
}
}
AndroidRuntime的start方法负责启动并管理Android虚拟机:
frameworks/base/core/jni/AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
static const String8 startSystemServer("start-system-server");
/*
* 'startSystemServer == true' means runtime is obsolete and not run from
* init.rc anymore, so we print out the boot start event here.
*/
for (size_t i = 0; i < options.size(); ++i) {
if (options[i] == startSystemServer) {
/* track our progress through the boot sequence */
const int LOG_BOOT_PROGRESS_START = 3000;
LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START, ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
}
}
const char* rootDir = getenv("ANDROID_ROOT");
if (rootDir == NULL) {
rootDir = "/system";
if (!hasDir("/system")) {
LOG_FATAL("No root directory specified, and /android does not exist.");
return;
}
setenv("ANDROID_ROOT", rootDir, 1);
}
//const char* kernelHack = getenv("LD_ASSUME_KERNEL");
/* start the virtual machine */
//step1,初始化jni环境,Init函数确定启动的虚拟机是Dalvik还是ART
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
//step2,启动虚拟机,mJavaVM代表启动后的虚拟机实例
if (startVm(&mJavaVM, &env, zygote) != 0) {
return;
}
//step3,虚拟机创建成功,执行回调函数通知调用者,这里的调用者就是app_process程序,所以实际执行的是app_main.cpp中的函数
onVmCreated(env);
/*
* Register android functions.
*/
//step4,注册native函数,都是写预设的jni函数
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
/*
* 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);
}
/*
* Start VM. This thread becomes the main thread of the VM, and will
* not return until the VM exits.
*/
//step5,执行目标对象的主函数,也即是zygoteInit的main函数
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 {
env->CallStaticVoidMethod(startClass, startMeth, strArray);
}
}
free(slashClassName);
}
上面的函数是启动虚拟机的通用流程,不管虚拟机是Dalvik还是ART,都遵循这个方式,以实现虚拟机的兼容性。
Step1,JniInvocation.init,在虚拟机启动前,需要初始化当前的运行环境,具体由JniInvacation.init函数完成。
libnativehelp/JniInvocation.cpp
bool JniInvocation::Init(const char* library) {
//获取虚拟机动态链接库的地址,默认值给定的是char* kLibraryFallback = "libart.so"
library = GetLibrary(library, buffer);
// Load with RTLD_NODELETE in order to ensure that libart.so is not unmapped when it is closed.
// This is due to the fact that it is possible that some threads might have yet to finish
// exiting even after JNI_DeleteJavaVM returns, which can lead to segfaults if the library is
// unloaded.
//打开虚拟机动态链接库
const int kDlopenFlags = RTLD_NOW | RTLD_NODELETE;
handle_ = dlopen(library, kDlopenFlags);
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, kDlopenFlags);
if (handle_ == NULL) {
ALOGE("Failed to dlopen %s: %s", library, dlerror());
return false;
}
}
//查找虚拟机库中3个重要的接口实现
if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetDefaultJavaVMInitArgs_),
"JNI_GetDefaultJavaVMInitArgs")) {
return false;
}
if (!FindSymbol(reinterpret_cast<void**>(&JNI_CreateJavaVM_),
"JNI_CreateJavaVM")) {
return false;
}
if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetCreatedJavaVMs_),
"JNI_GetCreatedJavaVMs")) {
return false;
}
return true;
}
获取到library库的名称(libart.so)后,通过dlopen把他打开并加载到内存,C语言为处理动态链接库提供了一些函数,如dlopen,dlsym,dladdr等,对应的实现在bionic/linker中,dlopen是以指定的模式打开动态链接库,RTLD_NOW表示在dlopen时直接解析所有未定义的符号,RTLD_NODELETE表示dlclose时不卸载动态库,那么后续如果该动态库重新被加载的话,其中的静态变量就不需要重新初始化了。
然后查找3个关键的接口实现,JNI_GetDefaultJavaVMInitArgs,JNI_CreateJavaVM,JNI_GetCreatedJavaVMs,分别保存在相应的变量中(JNI_GetDefaultJavaVMInitArgs_,JNI_CreateJavaVM_,JNI_GetCreatedJavaVMs_),这三个函数可以认为是Android虚拟机必须实现的通用接口,不管是art还是dalvik都要实现这3个接口,这样就能保证Android系统正确的使用他们。
Step2,StartVM,主要完成的工作有:
1)初始化虚拟机参数,ART跟Dalvik,JVM类似,支持一系列的配置参数,这些参数的默认值通常来自于系统属性,相关代码:
parseRuntimeOption("dalvik.vm.heapsize", heapsizeOptsBuf, "-Xmx", "16m");
parseCompilerRuntimeOption("dalvik.vm.dex2oat-Xms", dex2oatXmsFlagsBuf, "-Xms", "-Xcompiler-option");
2)StartVM的最后,调用JNI_CreateJavaVM,前面设置的启动参数会保存在变量nOptions中,然后通过JNI_CreateJavaVM这一标准接口传递给具体的虚拟机实现。JNI_CreateJavaVM成功返回,虚拟机就处于就绪状态了,可以接受jni调用了。
虚拟机分为java和native两个层面,这两层间的通信就是jni,通常虚拟机的创建和管理都是在native层,然后通过jni来与java层互访,JNI_CreateJavaVM成功执行后,会有一个JNIEnv类型的指针变量,就是pEnv,他是以指向指针的指针做为参数的。这个JNIEnv指针是访问JVM的关键,真正的实现是JNIEnvExt。
art/runtime/jni_env_ext.h ,从这里可以看出实现关系
struct JNIEnvExt : public JNIEnv {
static JNIEnvExt* Create(Thread* self, JavaVMExt* vm);
~JNIEnvExt();
}
Step3,onVmCreated,虚拟机成功创建完成,需要通过回调函数onVmCreate()通知用户,这里的调用者就是AndroidRuntime的继承类AppRuntime,
Step4,startReg,为虚拟机注册本地函数,
frameworks/base/core/jni/AndroidRuntime.cpp
int AndroidRuntime::startReg(JNIEnv* env)
{
ATRACE_NAME("RegisterAndroidNatives");
/*
* This hook causes all future threads created in this process to be
* attached to the JavaVM. (This needs to go away in favor of JNI
* Attach calls.)
*/
//这个调用会让后面创建的新线程都会hooked到JavaVM上。
androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);
ALOGV("--- registering native functions ---\n");
/*
* Every "register" function calls one or more things that return
* a local reference (e.g. FindClass). Because we haven't really
* started the VM yet, they're all getting stored in the base frame
* and never released. Use Push/Pop to manage the storage.
*/
//PushLocalFrame,PopLocalFrame的作用是管理局部引用的生命周期,要配套使用。
env->PushLocalFrame(200);
if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
env->PopLocalFrame(NULL);
return -1;
}
env->PopLocalFrame(NULL);
//createJavaThread("fubar", quickTest, (void*) "hello");
return 0;
}
register_jni_procs的作用是注册gRegJNI数组中的所有的nativeMethod:
static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_util_SeempLog),
REG_JNI(register_com_android_internal_os_RuntimeInit),
REG_JNI(register_android_os_SystemClock),
REG_JNI(register_android_util_EventLog),
REG_JNI(register_android_util_Log),
REG_JNI(register_android_util_MemoryIntArray),
REG_JNI(register_android_util_PathParser),
REG_JNI(register_android_app_admin_SecurityLog),
......
注册的过程是分别调用gRegJNI数组中每个元素,展开REG_JNI宏定义,实际执行的就是REG_JNI()括号中的函数,通过AndroidRuntime,这个函数最终会调用Java虚拟机中的RegisterNativeMethods方法,注册的过程就是把Java层的函数跟本地层的实现建立关联,这些java层函数和native函数的映射关系以JNINativeMethod gMethods[]数组来定义的,
typedef struct {
const char* name;
const char* signature;
void* fnPtr;
} JNINativeMethod;
宏定义REG_JNI中的每个函数都有一个这样的数组。从JNI的实现看,JVM所做的工作就是把这写本地函数设置为ArtMethod的JNI入口。
step5,AndroidRuntime::start的第五步,调用zygoteInit.java的main函数,正式启动一个Java程序。