Zygote进程启动过程的源代码分析
2012-11-21 11:30
387 查看
在Android系统中,所有的应用程序进程以及系统服务进程SystemServer都是由Zygote进程孕育(fork)出来的,zygote和system_server分别是Java世界的半边天,任何一个进程的死亡都会导致Java崩溃。
zygote本身是Native应用程序,与驱动内核无关。zygote最初的名字叫“app_process”,这个名字在Android.mk文件中指定,但在运行过程中被替换为"zygote"。
我们知道,Android系统是基于Linux内核的,而在Linux系统中,所有的进程都是init进程的子孙进程,也就是说,所有的进程都是直接或者间接地由init进程fork出来的。Zygote进程也不例外,它是在系统启动的过程,由init进程创建的。在系统启动脚本system/core/rootdir/init.rc文件中:
1.system/core/rootdir/init.rc:
[java] view
plaincopy
//关键字service告诉init进程创建一个名为"zygote"的进程,这个zygote进程要执行的程序是/system/bin/app_process,后面是要传给app_process的参数。
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
//socket关键字表示这个zygote进程需要一个名称为"zygote"的socket资源,这样,系统启动后,我们就可以在/dev/socket目录下看到有一个名为zygote的文件。这里定义的socket的类型为unix domain socket,它是用来作本地进程间通信用的
socket zygote stream 666
critical
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
onrestart restart mlistener
2.App_main.cpp
[java] view
plaincopy
int main(int argc, const char* const argv[])
{
//zygote 是由init进程fork而来,init.rc文件中为zygote进程设置的启动参数如下
//argc = 4
//argv = [-Xzygote, /system/bin, --zygote, --start-system-server]
// These are global variables in ProcessState.cpp
mArgC = argc;
mArgV = argv;
mArgLen = 0;
for (int i=0; i<argc; i++) {
mArgLen += strlen(argv[i]) + 1;
}
mArgLen--; // mArgLen = 48
AppRuntime runtime;
const char *arg;
const char *argv0;
argv0 = argv[0]; //-Xzygote
// Process command line arguments
// ignore argv[0]
argc--;
argv++;
//添加虚拟机参数选项
//addVmArguments(3, [/system/bin, --zygote, --start-system-server])结果返回 i=0
int i = runtime.addVmArguments(argc, argv);
// 设置虚拟机运行目录
if (i < argc) {
runtime.mParentDir = argv[i++]; //runtime.mParentDir =/system/bin
}
// i=1
// Next arg is startup classname or "--zygote"
if (i < argc) {
arg = argv[i++]; //arg = --zygote
//i=2
if (0 == strcmp("--zygote", arg)) {
//startSystemServer = true
bool startSystemServer = (i < argc) ? strcmp(argv[i], "--start-system-server") == 0 : false;
//设置argv0 的值为"zygote"
setArgv0(argv0, "zygote");
//设置进程名字
set_process_name("zygote");
// do last shutdown check
doLastShutDownCheck();
//调用Runtimed的start函数启动SystemServer进程,startSystemServer = true
runtime.start("com.android.internal.os.ZygoteInit",startSystemServer);
} else {
set_process_name(argv0);
runtime.mClassName = arg;
// Remainder of args get passed to startup class main()
runtime.mArgC = argc-i;
runtime.mArgV = argv+i;
LOGV("App process is starting with pid=%d, class=%s.\n",
getpid(), runtime.getClassName());
runtime.start();
}
} else {
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
return 10;
}
}
这个函数的主要作用就是创建一个AppRuntime变量,然后调用它的start成员函数。AppRuntime类的声明和实现在App_main.cpp中,派生于AndroidRuntime类
3.AndroidRuntime.cpp
[java] view
plaincopy
void AndroidRuntime::start(const char* className, const bool startSystemServer)
{
//className = "com.android.internal.os.ZygoteInit"
//startSystemServer = true
LOGD("\n>>>>>> AndroidRuntime START %s <<<<<<\n",className != NULL ? className : "(unknown)");
char* slashClassName = NULL;
char* cp;
JNIEnv* env;
blockSigpipe();
/*
* 'startSystemServer == true' means runtime is obslete and not run from
* init.rc anymore, so we print out the boot start event here.
*/
if (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)));
}
//获取环境变量android_root的根目录
const char* rootDir = getenv("ANDROID_ROOT");
if (rootDir == NULL) {
rootDir = "/system"; //如果获取结果为Null,则设置为"/system"
if (!hasDir("/system")) {
LOG_FATAL("No root directory specified, and /android does not exist.");
goto bail;
}
setenv("ANDROID_ROOT", rootDir, 1);//重新设置环境变量ANDROID_ROOT
}
//const char* kernelHack = getenv("LD_ASSUME_KERNEL");
//LOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);
/* 启动虚拟机 */
if (startVm(&mJavaVM, &env) != 0)
goto bail;
/*
* 注册JNI函数
*/
if (startReg(env) < 0) {
LOGE("Unable to register all android natives\n");
goto bail;
}
/*
* We want to call main() with a String array with arguments in it.
* At present we only have one argument, the class name. Create an
* array to hold it.
*/
jclass stringClass;
jobjectArray strArray;
jstring classNameStr;
jstring startSystemServerStr;
//通过JNI查找java的java.lang.String类
stringClass = env->FindClass("java/lang/String");
assert(stringClass != NULL);
//创建字符串数组String strArray[] = new String[2];
strArray = env->NewObjectArray(2, stringClass, NULL);
assert(strArray != NULL);
//创建字符串classNameStr = new String("com.android.internal.os.ZygoteInit")
classNameStr = env->NewStringUTF(className);
assert(classNameStr != NULL);
//设置字符串数组元素strArray[0]="com.android.internal.os.ZygoteInit"
env->SetObjectArrayElement(strArray, 0, classNameStr);
//创建字符串startSystemServerStr= new String("true")
startSystemServerStr = env->NewStringUTF(startSystemServer ? "true" : "false");
//设置字符串数组元素strArray[1]="true"
env->SetObjectArrayElement(strArray, 1, startSystemServerStr);
/*
* Start VM. This thread becomes the main thread of the VM, and will
* not return until the VM exits.
*/
jclass startClass;
jmethodID startMeth;
//将字符串className 复制到slashClassName
slashClassName = strdup(className);
//为符合JNI规范,将com.android.internal.os.ZygoteInit中的.换成/,变为slashClassName = com/android/internal/os/ZygoteInit
for (cp = slashClassName; *cp != '\0'; cp++)
if (*cp == '.')
*cp = '/';
//查找Java类com/android/internal/os/ZygoteInit
startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
LOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
//找到ZygoteInit类的静态main方法的jMethodID
startMeth = env->GetStaticMethodID(startClass, "main","([Ljava/lang/String;)V");
if (startMeth == NULL) {
LOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
//通过JNI调用ZygoteInit类的main函数,传递的参数为:
//startClass = ZygoteInit
//startMeth = main
//strArray =["com.android.internal.os.ZygoteInit","true"]
//在调用ZygoteInit类的main方法后,zygote就进入了java世界
env->CallStaticVoidMethod(startClass, startMeth, strArray);
#if 0
if (env->ExceptionCheck())
threadExitUncaughtException(env);
#endif
}
}
LOGD("Shutting down VM\n");
if (mJavaVM->DetachCurrentThread() != JNI_OK)
LOGW("Warning: unable to detach main thread\n");
if (mJavaVM->DestroyJavaVM() != 0)
LOGW("Warning: VM did not shut down cleanly\n");
bail:
free(slashClassName);
}
这个函数的作用是启动Android系统运行时库,它主要做了三件事情:
一是调用函数startVM启动虚拟机;
二是调用函数startReg注册JNI方法;
三是调用了com.android.internal.os.ZygoteInit类的main函数;
4.AndroidRuntime.cpp 启动虚拟机
[java] view
plaincopy
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv)
{
int result = -1;
JavaVMInitArgs initArgs; //虚拟机初始化参数
JavaVMOption opt; //虚拟机选项
char propBuf[PROPERTY_VALUE_MAX];
char stackTraceFileBuf[PROPERTY_VALUE_MAX];
char dexoptFlagsBuf[PROPERTY_VALUE_MAX];
char enableAssertBuf[sizeof("-ea:")-1 + PROPERTY_VALUE_MAX];
char jniOptsBuf[sizeof("-Xjniopts:")-1 + PROPERTY_VALUE_MAX];
char heapsizeOptsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX];
char extraOptsBuf[PROPERTY_VALUE_MAX];
char* stackTraceFile = NULL;
bool checkJni = false;
bool checkDexSum = false;
bool logStdio = false;
enum {
kEMDefault,
kEMIntPortable,
kEMIntFast,
#if defined(WITH_JIT)
kEMJitCompiler,
#endif
} executionMode = kEMDefault;
property_get("dalvik.vm.checkjni", propBuf, ""); //读取"dalvik.vm.checkjni"属性值,“true” : “false”
if (strcmp(propBuf, "true") == 0) {
checkJni = true;
} else if (strcmp(propBuf, "false") != 0) {
/* property is neither true nor false; fall back on kernel parameter */
property_get("ro.kernel.android.checkjni", propBuf, "");
if (propBuf[0] == '1') {
checkJni = true;
}
}
property_get("dalvik.vm.execution-mode", propBuf, "");//读取"dalvik.vm.execution-mode"属性值,“int:portable” : “int:fast”: “int:jit”
if (strcmp(propBuf, "int:portable") == 0) {
executionMode = kEMIntPortable;
} else if (strcmp(propBuf, "int:fast") == 0) {
executionMode = kEMIntFast;
#if defined(WITH_JIT)
} else if (strcmp(propBuf, "int:jit") == 0) {
executionMode = kEMJitCompiler;
#endif
}
property_get("dalvik.vm.stack-trace-file", stackTraceFileBuf, "");//读取"dalvik.vm.stack-trace-file"属性值
property_get("dalvik.vm.check-dex-sum", propBuf, "");//读取"dalvik.vm.check-dex-sum"属性值,“true” : “false”
if (strcmp(propBuf, "true") == 0) {
checkDexSum = true;
}
property_get("log.redirect-stdio", propBuf, "");
if (strcmp(propBuf, "true") == 0) {
logStdio = true;
}
strcpy(enableAssertBuf, "-ea:");
property_get("dalvik.vm.enableassertions", enableAssertBuf+4, "");//读取"dalvik.vm.enableassertions"属性值
strcpy(jniOptsBuf, "-Xjniopts:");
property_get("dalvik.vm.jniopts", jniOptsBuf+10, "");//读取"dalvik.vm.jniopts"属性值
/* route exit() to our handler */
opt.extraInfo = (void*) runtime_exit; //设置退出函数
opt.optionString = "exit";
mOptions.add(opt);
/* route fprintf() to our handler */
opt.extraInfo = (void*) runtime_vfprintf;//设置打印输出函数
opt.optionString = "vfprintf";
mOptions.add(opt);
opt.extraInfo = NULL;
/* enable verbose; standard options are { jni, gc, class } */
//options[curOpt++].optionString = "-verbose:jni";
opt.optionString = "-verbose:gc";
mOptions.add(opt);
//options[curOpt++].optionString = "-verbose:class";
strcpy(heapsizeOptsBuf, "-Xmx");
property_get("dalvik.vm.heapsize", heapsizeOptsBuf+4, "16m");//读取"dalvik.vm.heapsize"属性值
//LOGI("Heap size: %s", heapsizeOptsBuf);
opt.optionString = heapsizeOptsBuf;
mOptions.add(opt);
/*
* Enable or disable dexopt features, such as bytecode verification and
* calculation of register maps for precise GC.
*/
property_get("dalvik.vm.dexopt-flags", dexoptFlagsBuf, "");//读取"dalvik.vm.dexopt-flags"属性值
if (dexoptFlagsBuf[0] != '\0') {
const char* opc;
const char* val;
opc = strstr(dexoptFlagsBuf, "v="); /* verification */
if (opc != NULL) {
switch (*(opc+2)) {
case 'n': val = "-Xverify:none"; break;
case 'r': val = "-Xverify:remote"; break;
case 'a': val = "-Xverify:all"; break;
default: val = NULL; break;
}
if (val != NULL) {
opt.optionString = val;
mOptions.add(opt);
}
}
opc = strstr(dexoptFlagsBuf, "o="); /* optimization */
if (opc != NULL) {
switch (*(opc+2)) {
case 'n': val = "-Xdexopt:none"; break;
case 'v': val = "-Xdexopt:verified"; break;
case 'a': val = "-Xdexopt:all"; break;
default: val = NULL; break;
}
if (val != NULL) {
opt.optionString = val;
mOptions.add(opt);
}
}
opc = strstr(dexoptFlagsBuf, "m=y"); /* register map */
if (opc != NULL) {
opt.optionString = "-Xgenregmap";
mOptions.add(opt);
/* turn on precise GC while we're at it */
opt.optionString = "-Xgc:precise";
mOptions.add(opt);
}
}
/* enable debugging; set suspend=y to pause during VM init */
#ifdef HAVE_ANDROID_OS
/* use android ADB transport */
opt.optionString ="-agentlib:jdwp=transport=dt_android_adb,suspend=n,server=y";
#else
/* use TCP socket; address=0 means start at port 8000 and probe up */
LOGI("Using TCP socket for JDWP\n");
opt.optionString ="-agentlib:jdwp=transport=dt_socket,suspend=n,server=y,address=0";
#endif
mOptions.add(opt);
char enableDPBuf[sizeof("-Xdeadlockpredict:") + PROPERTY_VALUE_MAX];
property_get("dalvik.vm.deadlock-predict", propBuf, "");
if (strlen(propBuf) > 0) {
strcpy(enableDPBuf, "-Xdeadlockpredict:");
strcat(enableDPBuf, propBuf);
opt.optionString = enableDPBuf;
mOptions.add(opt);
}
LOGD("CheckJNI is %s\n", checkJni ? "ON" : "OFF");
if (checkJni) {
/* extended JNI checking */
opt.optionString = "-Xcheck:jni";
mOptions.add(opt);
/* set a cap on JNI global references */
opt.optionString = "-Xjnigreflimit:2000";
mOptions.add(opt);
/* with -Xcheck:jni, this provides a JNI function call trace */
//opt.optionString = "-verbose:jni";
//mOptions.add(opt);
}
char lockProfThresholdBuf[sizeof("-Xlockprofthreshold:") + sizeof(propBuf)];
property_get("dalvik.vm.lockprof.threshold", propBuf, "");
if (strlen(propBuf) > 0) {
strcpy(lockProfThresholdBuf, "-Xlockprofthreshold:");
strcat(lockProfThresholdBuf, propBuf);
opt.optionString = lockProfThresholdBuf;
mOptions.add(opt);
}
#if defined(WITH_JIT)
/* Force interpreter-only mode for selected opcodes. Eg "1-0a,3c,f1-ff" */
char jitOpBuf[sizeof("-Xjitop:") + PROPERTY_VALUE_MAX];
property_get("dalvik.vm.jit.op", propBuf, "");
if (strlen(propBuf) > 0) {
strcpy(jitOpBuf, "-Xjitop:");
strcat(jitOpBuf, propBuf);
opt.optionString = jitOpBuf;
mOptions.add(opt);
}
/* Force interpreter-only mode for selected methods */
char jitMethodBuf[sizeof("-Xjitmethod:") + PROPERTY_VALUE_MAX];
property_get("dalvik.vm.jit.method", propBuf, "");
if (strlen(propBuf) > 0) {
strcpy(jitMethodBuf, "-Xjitmethod:");
strcat(jitMethodBuf, propBuf);
opt.optionString = jitMethodBuf;
mOptions.add(opt);
}
#endif
if (executionMode == kEMIntPortable) {
opt.optionString = "-Xint:portable";
mOptions.add(opt);
} else if (executionMode == kEMIntFast) {
opt.optionString = "-Xint:fast";
mOptions.add(opt);
#if defined(WITH_JIT)
} else if (executionMode == kEMJitCompiler) {
opt.optionString = "-Xint:jit";
mOptions.add(opt);
#endif
}
if (checkDexSum) {
/* perform additional DEX checksum tests */
opt.optionString = "-Xcheckdexsum";
mOptions.add(opt);
}
if (logStdio) {
/* convert stdout/stderr to log messages */
opt.optionString = "-Xlog-stdio";
mOptions.add(opt);
}
if (enableAssertBuf[4] != '\0') {
/* accept "all" to mean "all classes and packages" */
if (strcmp(enableAssertBuf+4, "all") == 0)
enableAssertBuf[3] = '\0';
LOGI("Assertions enabled: '%s'\n", enableAssertBuf);
opt.optionString = enableAssertBuf;
mOptions.add(opt);
} else {
LOGV("Assertions disabled\n");
}
if (jniOptsBuf[10] != '\0') {
LOGI("JNI options: '%s'\n", jniOptsBuf);
opt.optionString = jniOptsBuf;
mOptions.add(opt);
}
if (stackTraceFileBuf[0] != '\0') {
static const char* stfOptName = "-Xstacktracefile:";
stackTraceFile = (char*) malloc(strlen(stfOptName) +
strlen(stackTraceFileBuf) +1);
strcpy(stackTraceFile, stfOptName);
strcat(stackTraceFile, stackTraceFileBuf);
opt.optionString = stackTraceFile;
mOptions.add(opt);
}
/* extra options; parse this late so it overrides others */
property_get("dalvik.vm.extra-opts", extraOptsBuf, "");
parseExtraOpts(extraOptsBuf);
/* Set the properties for locale */
{
char langOption[sizeof("-Duser.language=") + 3];
char regionOption[sizeof("-Duser.region=") + 3];
strcpy(langOption, "-Duser.language=");
strcpy(regionOption, "-Duser.region=");
readLocale(langOption, regionOption);
opt.extraInfo = NULL;
opt.optionString = langOption;
mOptions.add(opt);
opt.optionString = regionOption;
mOptions.add(opt);
}
/*
* We don't have /tmp on the device, but we often have an SD card. Apps
* shouldn't use this, but some test suites might want to exercise it.
*/
opt.optionString = "-Djava.io.tmpdir=/sdcard";
mOptions.add(opt);
initArgs.version = JNI_VERSION_1_4;
initArgs.options = mOptions.editArray();
initArgs.nOptions = mOptions.size();
initArgs.ignoreUnrecognized = JNI_FALSE;
/*
* 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.
*调用JNI_CreateJavaVM函数创建虚拟机,关于虚拟机创建过程可参考dalvik\vm\Jni.c
*/
if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
LOGE("JNI_CreateJavaVM failed\n");
goto bail;
}
result = 0;
bail:
free(stackTraceFile);
return result;
}
5.AndroidRuntime.cpp 注册JNI函数
第4步中已经创建好了虚拟机,因此需要给该虚拟机注册一些JNI函数。
[java] view
plaincopy
int AndroidRuntime::startReg(JNIEnv* env)
{
/*
* 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.) 设置线程创建函数为javaCreateThreadEtc
*/
androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);
LOGV("--- 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.
*/
env->PushLocalFrame(200);
//注册JNI函数,所有的JNI函数存放在gRegJNI全局数组中
if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
env->PopLocalFrame(NULL);
return -1;
}
env->PopLocalFrame(NULL);
//createJavaThread("fubar", quickTest, (void*) "hello");
return 0;
}
[java] view
plaincopy
//JNI函数注册方法
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
LOGD("----------!!! %s failed to load\n", array[i].mName);
#endif
return -1;
}
}
return 0;
}
[html] view
plaincopy
//gRegJNI全局数组中
static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_debug_JNITest),
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_FloatMath),
REG_JNI(register_android_text_format_Time),
REG_JNI(register_android_pim_EventRecurrence),
REG_JNI(register_android_content_AssetManager),
REG_JNI(register_android_content_StringBlock),
REG_JNI(register_android_content_XmlBlock),
REG_JNI(register_android_emoji_EmojiFactory),
REG_JNI(register_android_security_Md5MessageDigest),
REG_JNI(register_android_text_AndroidCharacter),
REG_JNI(register_android_text_AndroidBidi),
REG_JNI(register_android_text_KeyCharacterMap),
REG_JNI(register_android_os_Process),
REG_JNI(register_android_os_Binder),
REG_JNI(register_android_view_Display),
REG_JNI(register_android_nio_utils),
REG_JNI(register_android_graphics_PixelFormat),
REG_JNI(register_android_graphics_Graphics),
REG_JNI(register_android_view_Surface),
REG_JNI(register_android_view_ViewRoot),
REG_JNI(register_com_google_android_gles_jni_EGLImpl),
REG_JNI(register_com_google_android_gles_jni_GLImpl),
REG_JNI(register_android_opengl_jni_GLES10),
REG_JNI(register_android_opengl_jni_GLES10Ext),
REG_JNI(register_android_opengl_jni_GLES11),
REG_JNI(register_android_opengl_jni_GLES11Ext),
REG_JNI(register_android_opengl_jni_GLES20),
REG_JNI(register_android_graphics_Bitmap),
REG_JNI(register_android_graphics_BitmapFactory),
REG_JNI(register_android_graphics_BitmapRegionDecoder),
REG_JNI(register_android_graphics_Camera),
REG_JNI(register_android_graphics_Canvas),
REG_JNI(register_android_graphics_ColorFilter),
REG_JNI(register_android_graphics_DrawFilter),
REG_JNI(register_android_graphics_Interpolator),
REG_JNI(register_android_graphics_LayerRasterizer),
REG_JNI(register_android_graphics_MaskFilter),
REG_JNI(register_android_graphics_Matrix),
REG_JNI(register_android_graphics_Movie),
REG_JNI(register_android_graphics_NinePatch),
REG_JNI(register_android_graphics_Paint),
REG_JNI(register_android_graphics_Path),
REG_JNI(register_android_graphics_PathMeasure),
REG_JNI(register_android_graphics_PathEffect),
REG_JNI(register_android_graphics_Picture),
REG_JNI(register_android_graphics_PorterDuff),
REG_JNI(register_android_graphics_Rasterizer),
REG_JNI(register_android_graphics_Region),
REG_JNI(register_android_graphics_Shader),
REG_JNI(register_android_graphics_Typeface),
REG_JNI(register_android_graphics_Xfermode),
REG_JNI(register_android_graphics_YuvImage),
REG_JNI(register_com_android_internal_graphics_NativeUtils),
REG_JNI(register_android_database_CursorWindow),
REG_JNI(register_android_database_SQLiteCompiledSql),
REG_JNI(register_android_database_SQLiteDatabase),
REG_JNI(register_android_database_SQLiteDebug),
REG_JNI(register_android_database_SQLiteProgram),
REG_JNI(register_android_database_SQLiteQuery),
REG_JNI(register_android_database_SQLiteStatement),
REG_JNI(register_android_os_Debug),
REG_JNI(register_android_os_FileObserver),
REG_JNI(register_android_os_FileUtils),
REG_JNI(register_android_os_MessageQueue),
REG_JNI(register_android_os_ParcelFileDescriptor),
REG_JNI(register_android_os_Power),
REG_JNI(register_android_os_StatFs),
REG_JNI(register_android_os_SystemProperties),
REG_JNI(register_android_os_UEventObserver),
REG_JNI(register_android_net_LocalSocketImpl),
REG_JNI(register_android_net_NetworkUtils),
REG_JNI(register_android_net_TrafficStats),
REG_JNI(register_android_net_wifi_WifiManager),
REG_JNI(register_android_nfc_NdefMessage),
REG_JNI(register_android_nfc_NdefRecord),
REG_JNI(register_android_os_MemoryFile),
REG_JNI(register_com_android_internal_os_ZygoteInit),
REG_JNI(register_android_hardware_Camera),
REG_JNI(register_android_hardware_SensorManager),
REG_JNI(register_android_media_AudioRecord),
REG_JNI(register_android_media_AudioSystem),
REG_JNI(register_android_media_AudioTrack),
REG_JNI(register_android_media_JetPlayer),
REG_JNI(register_android_media_ToneGenerator),
REG_JNI(register_android_opengl_classes),
REG_JNI(register_android_bluetooth_HeadsetBase),
REG_JNI(register_android_bluetooth_BluetoothAudioGateway),
REG_JNI(register_android_bluetooth_BluetoothSocket),
REG_JNI(register_android_bluetooth_ScoSocket),
REG_JNI(register_android_server_BluetoothService),
REG_JNI(register_android_server_BluetoothEventLoop),
REG_JNI(register_android_server_BluetoothA2dpService),
REG_JNI(register_android_server_Watchdog),
REG_JNI(register_android_message_digest_sha1),
REG_JNI(register_android_ddm_DdmHandleNativeHeap),
REG_JNI(register_android_backup_BackupDataInput),
REG_JNI(register_android_backup_BackupDataOutput),
REG_JNI(register_android_backup_FileBackupHelperBase),
REG_JNI(register_android_backup_BackupHelperDispatcher),
REG_JNI(register_android_hardware_fm_fmradio),
REG_JNI(register_android_app_NativeActivity),
REG_JNI(register_android_view_InputChannel),
REG_JNI(register_android_view_InputQueue),
REG_JNI(register_android_view_KeyEvent),
REG_JNI(register_android_view_MotionEvent),
REG_JNI(register_android_content_res_ObbScanner),
REG_JNI(register_android_content_res_Configuration),
};
6.ZygoteInit.java 调用了com.android.internal.os.ZygoteInit类的main函数
[java] view
plaincopy
public static void main(String argv[]) {
//传入的参数argv = ["com.android.internal.os.ZygoteInit","true"]
try {
//设置虚拟机的最小堆栈大小
VMRuntime.getRuntime().setMinimumHeapSize(5 * 1024 * 1024);
// Start profiling the zygote initialization.启动性能统计
SamplingProfilerIntegration.start();
//注册zygote等待客户端连接的socket
registerZygoteSocket();
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, SystemClock.uptimeMillis());
//预加载java类和资源
preloadClasses();
preloadResources();
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,SystemClock.uptimeMillis());
// Finish profiling the zygote initialization.结束统计并生成结果文件
SamplingProfilerIntegration.writeZygoteSnapshot();
// Do an initial gc to clean up after startup,执行垃圾回收
gc();
// If requested, start system server directly from Zygote
if (argv.length != 2) {
throw new RuntimeException(argv[0] + USAGE_STRING);
}
if (argv[1].equals("true")) {
//启动SystemServer进程
startSystemServer();
} else if (!argv[1].equals("false")) {
throw new RuntimeException(argv[0] + USAGE_STRING);
}
Log.i(TAG, "Accepting command socket connections");
//boolean ZYGOTE_FORK_MODE = false; 因此调用runSelectLoopMode()函数
if (ZYGOTE_FORK_MODE) {
runForkMode();
} else {
runSelectLoopMode();
}
closeServerSocket(); //关闭socket
} catch (MethodAndArgsCaller caller) {
//捕获SytemServer进程调用RuntimeInit.java 中zygoteInit函数抛出的MethodAndArgsCaller异常
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}
该main函数的作用:
<1>.调用registerZygoteSocket函数创建了一个socket接口,建立IPC通信的服务端;
<2> preloadClasses,preloadResources函数预加载类和资源
<2>.调用startSystemServer函数来启动SystemServer组件;
<3>.调用runSelectLoopMode函数进入一个无限循环在前面创建的socket接口上等待ActivityManagerService请求创建新的应用程序进程。
7.ZygoteInit.java 建立socket通信服务端
zygote 并没有采用binder通信机制,而是采用基于AF_UNIX类型的socket通信方式
[java] view
plaincopy
private static void registerZygoteSocket() {
if (sServerSocket == null) {
int fileDesc;
try {
//从环境变量中获取文件句柄,这个socket接口是通过文件描述符来创建的,这个文件描符代表的就是我们前面说的/dev/socket/zygote文件了。这个文件描述符是通过环境变量ANDROID_SOCKET_ENV得到的,关于socket的创建及环境变量的设置请参考init进程源码分析
String env = System.getenv(ANDROID_SOCKET_ENV);
fileDesc = Integer.parseInt(env);
} catch (RuntimeException ex) {
throw new RuntimeException(ANDROID_SOCKET_ENV + " unset or invalid", ex);
}
try {
//创建服务端socket,该socket将监听并接受客户端请求
sServerSocket = new LocalServerSocket(createFileDescriptor(fileDesc));
} catch (IOException ex) {
throw new RuntimeException("Error binding to local socket '" + fileDesc + "'", ex);
}
}
}
8.ZygoteInit.java 预加载类和资源
[java] view
plaincopy
private static void preloadClasses() {
final VMRuntime runtime = VMRuntime.getRuntime();
//通过反射机制获取输入流,类资源文件为"preloaded-clprr"
InputStream is = ZygoteInit.class.getClassLoader().getResourceAsStream(PRELOADED_CLASSES);
if (is == null) {
Log.e(TAG, "Couldn't find " + PRELOADED_CLASSES + ".");
} else {
Log.i(TAG, "Preloading classes...");
long startTime = SystemClock.uptimeMillis();
// Drop root perms while running static initializers.
//设置有效组ID和有效用户ID
setEffectiveGroup(UNPRIVILEGED_GID);
setEffectiveUser(UNPRIVILEGED_UID);
// Alter the target heap utilization. With explicit GCs this
// is not likely to have any effect.
float defaultUtilization = runtime.getTargetHeapUtilization();
runtime.setTargetHeapUtilization(0.8f);
// Start with a clean slate.
runtime.gcSoftReferences();
runtime.runFinalizationSync();
Debug.startAllocCounting();
try {
BufferedReader br= new BufferedReader(new InputStreamReader(is), 256);
int count = 0;
String line;
//一行一行读取文件内容
while ((line = br.readLine()) != null) {
// Skip comments and blank lines.
line = line.trim();
if (line.startsWith("#") || line.equals("")) {
continue;
}
try {
if (Config.LOGV) {
Log.v(TAG, "Preloading " + line + "...");
}
//通过Java反射机制加载类,每一行储存的是类名
Class.forName(line);
if (Debug.getGlobalAllocSize() > PRELOAD_GC_THRESHOLD) {
if (Config.LOGV) {
Log.v(TAG," GC at " + Debug.getGlobalAllocSize());
}
runtime.gcSoftReferences();
runtime.runFinalizationSync();
Debug.resetGlobalAllocSize();
}
count++;
} catch (ClassNotFoundException e) {
Log.w(TAG, "Class not found for preloading: " + line);
} catch (Throwable t) {
Log.e(TAG, "Error preloading " + line + ".", t);
if (t instanceof Error) {
throw (Error) t;
}
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
}
throw new RuntimeException(t);
}
}
Log.i(TAG, "...preloaded " + count + " classes in "
+ (SystemClock.uptimeMillis()-startTime) + "ms.");
} catch (IOException e) {
Log.e(TAG, "Error reading " + PRELOADED_CLASSES + ".", e);
} finally {
// Restore default.
runtime.setTargetHeapUtilization(defaultUtilization);
Debug.stopAllocCounting();
// Bring back root. We'll need it later.
setEffectiveUser(ROOT_UID);
setEffectiveGroup(ROOT_GID);
}
}
}
preloadClasses 执行时间比较长,也是导致android系统启动慢的原因。
加载共享资源
[java] view
plaincopy
private static void preloadResources() {
final VMRuntime runtime = VMRuntime.getRuntime();
Debug.startAllocCounting();
try {
runtime.gcSoftReferences();
runtime.runFinalizationSync();
mResources = Resources.getSystem();
mResources.startPreloading();
if (PRELOAD_RESOURCES) {
Log.i(TAG, "Preloading resources...");
long startTime = SystemClock.uptimeMillis();
TypedArray ar = mResources.obtainTypedArray(com.android.internal.R.array.preloaded_drawables);
int N = preloadDrawables(runtime, ar);
Log.i(TAG, "...preloaded " + N + " resources in "+ (SystemClock.uptimeMillis()-startTime) + "ms.");
startTime = SystemClock.uptimeMillis();
ar = mResources.obtainTypedArray(
com.android.internal.R.array.preloaded_color_state_lists);
N = preloadColorStateLists(runtime, ar);
Log.i(TAG, "...preloaded " + N + " resources in "+ (SystemClock.uptimeMillis()-startTime) + "ms.");
}
mResources.finishPreloading();
} catch (RuntimeException e) {
Log.w(TAG, "Failure preloading resources", e);
} finally {
Debug.stopAllocCounting();
}
}
9.ZygoteInit.java 启动SystemServer
[java] view
plaincopy
private static boolean startSystemServer()
throws MethodAndArgsCaller, RuntimeException {
/* Hardcoded command line to start the system server */
String args[] = {
"--setuid=1000",
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,3001,3002,3003",
"--capabilities=130104352,130104352",
"--runtime-init",
"--nice-name=system_server",
"com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs = null;
int pid;
try {
parsedArgs = new ZygoteConnection.Arguments(args); //把字符串数组中的参数转换为Arguments对象
/*
* Enable debugging of the system process if *either* the command line flags
* indicate it should be debuggable or the ro.debuggable system property
* is set to "1"
*/
int debugFlags = parsedArgs.debugFlags;
if ("1".equals(SystemProperties.get("ro.debuggable")))
debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
/* fork一个子进程作为SystemServer进程*/
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids, debugFlags, null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
/* For child process */
if (pid == 0) {
//SystemServer进程的初始化设置
handleSystemServerProcess(parsedArgs);
}
return true;
}
Zygote进程通过Zygote.forkSystemServer函数来创建一个新的进程来启动SystemServer组件,返回值pid等0的地方就是新的进程要执行的路径,即新创建的进程会执行handleSystemServerProcess函数。
10.ZygoteInit.java 循环等待客户端的连接
[java] view
plaincopy
private static void runSelectLoopMode() throws MethodAndArgsCaller {
ArrayList<FileDescriptor> fds = new ArrayList(); //存储所有客户端连接的socket文件句柄
ArrayList<ZygoteConnection> peers = new ArrayList();//存储所有客户端连接
FileDescriptor[] fdArray = new FileDescriptor[4];
fds.add(sServerSocket.getFileDescriptor());//保存先前创建用于等待客户端连接的服务端socket
peers.add(null);
int loopCount = GC_LOOP_COUNT;
while (true) {
int index;
/*
* Call gc() before we block in select().
* It's work that has to be done anyway, and it's better
* to avoid making every child do it. It will also
* madvise() any free memory as a side-effect.
*
* Don't call it every time, because walking the entire
* heap is a lot of overhead to free a few hundred bytes.
*/
if (loopCount <= 0) {
gc();
loopCount = GC_LOOP_COUNT;
} else {
loopCount--;
}
try {
fdArray = fds.toArray(fdArray);
//selectReadable内部调用select,使用多路复用I/O模型
//当有客户端连接时,selectReadable返回
index = selectReadable(fdArray);
} catch (IOException ex) {
throw new RuntimeException("Error in select()", ex);
}
if (index < 0) {
throw new RuntimeException("Error in select()");
} else if (index == 0) {
//有一个客户端连接
ZygoteConnection newPeer = acceptCommandPeer();
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
boolean done;
//客户端发送了请求,peers.get(index)获取当前客户端的ZygoteConnection,并调用当前连接的runOnce()函数创建新的应用程序
done = peers.get(index).runOnce();
if (done) {
peers.remove(index);
fds.remove(index);
}
}
}
}
zygote总结:
1.创建AppRuntime对象,并调用它的start函数;
2.调用startVm创建Java虚拟机;
3.调用startReg函数来注册JNI函数;
4.调用ZygoteInit类的main函数,从此就进入了Java世界;
5.调用registerZygoteSocket 注册一个服务端socket;
6.调用preloadClasses 函数加载类资源;
7.调用preloadResources函数加载系统资源;
8.调用startSystemServer函数创建SystemServer进程;
9.调用runSelectLoopMode函数进入服务端socket监听;
zygote本身是Native应用程序,与驱动内核无关。zygote最初的名字叫“app_process”,这个名字在Android.mk文件中指定,但在运行过程中被替换为"zygote"。
我们知道,Android系统是基于Linux内核的,而在Linux系统中,所有的进程都是init进程的子孙进程,也就是说,所有的进程都是直接或者间接地由init进程fork出来的。Zygote进程也不例外,它是在系统启动的过程,由init进程创建的。在系统启动脚本system/core/rootdir/init.rc文件中:
1.system/core/rootdir/init.rc:
[java] view
plaincopy
//关键字service告诉init进程创建一个名为"zygote"的进程,这个zygote进程要执行的程序是/system/bin/app_process,后面是要传给app_process的参数。
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
//socket关键字表示这个zygote进程需要一个名称为"zygote"的socket资源,这样,系统启动后,我们就可以在/dev/socket目录下看到有一个名为zygote的文件。这里定义的socket的类型为unix domain socket,它是用来作本地进程间通信用的
socket zygote stream 666
critical
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
onrestart restart mlistener
2.App_main.cpp
[java] view
plaincopy
int main(int argc, const char* const argv[])
{
//zygote 是由init进程fork而来,init.rc文件中为zygote进程设置的启动参数如下
//argc = 4
//argv = [-Xzygote, /system/bin, --zygote, --start-system-server]
// These are global variables in ProcessState.cpp
mArgC = argc;
mArgV = argv;
mArgLen = 0;
for (int i=0; i<argc; i++) {
mArgLen += strlen(argv[i]) + 1;
}
mArgLen--; // mArgLen = 48
AppRuntime runtime;
const char *arg;
const char *argv0;
argv0 = argv[0]; //-Xzygote
// Process command line arguments
// ignore argv[0]
argc--;
argv++;
//添加虚拟机参数选项
//addVmArguments(3, [/system/bin, --zygote, --start-system-server])结果返回 i=0
int i = runtime.addVmArguments(argc, argv);
// 设置虚拟机运行目录
if (i < argc) {
runtime.mParentDir = argv[i++]; //runtime.mParentDir =/system/bin
}
// i=1
// Next arg is startup classname or "--zygote"
if (i < argc) {
arg = argv[i++]; //arg = --zygote
//i=2
if (0 == strcmp("--zygote", arg)) {
//startSystemServer = true
bool startSystemServer = (i < argc) ? strcmp(argv[i], "--start-system-server") == 0 : false;
//设置argv0 的值为"zygote"
setArgv0(argv0, "zygote");
//设置进程名字
set_process_name("zygote");
// do last shutdown check
doLastShutDownCheck();
//调用Runtimed的start函数启动SystemServer进程,startSystemServer = true
runtime.start("com.android.internal.os.ZygoteInit",startSystemServer);
} else {
set_process_name(argv0);
runtime.mClassName = arg;
// Remainder of args get passed to startup class main()
runtime.mArgC = argc-i;
runtime.mArgV = argv+i;
LOGV("App process is starting with pid=%d, class=%s.\n",
getpid(), runtime.getClassName());
runtime.start();
}
} else {
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
return 10;
}
}
这个函数的主要作用就是创建一个AppRuntime变量,然后调用它的start成员函数。AppRuntime类的声明和实现在App_main.cpp中,派生于AndroidRuntime类
3.AndroidRuntime.cpp
[java] view
plaincopy
void AndroidRuntime::start(const char* className, const bool startSystemServer)
{
//className = "com.android.internal.os.ZygoteInit"
//startSystemServer = true
LOGD("\n>>>>>> AndroidRuntime START %s <<<<<<\n",className != NULL ? className : "(unknown)");
char* slashClassName = NULL;
char* cp;
JNIEnv* env;
blockSigpipe();
/*
* 'startSystemServer == true' means runtime is obslete and not run from
* init.rc anymore, so we print out the boot start event here.
*/
if (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)));
}
//获取环境变量android_root的根目录
const char* rootDir = getenv("ANDROID_ROOT");
if (rootDir == NULL) {
rootDir = "/system"; //如果获取结果为Null,则设置为"/system"
if (!hasDir("/system")) {
LOG_FATAL("No root directory specified, and /android does not exist.");
goto bail;
}
setenv("ANDROID_ROOT", rootDir, 1);//重新设置环境变量ANDROID_ROOT
}
//const char* kernelHack = getenv("LD_ASSUME_KERNEL");
//LOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);
/* 启动虚拟机 */
if (startVm(&mJavaVM, &env) != 0)
goto bail;
/*
* 注册JNI函数
*/
if (startReg(env) < 0) {
LOGE("Unable to register all android natives\n");
goto bail;
}
/*
* We want to call main() with a String array with arguments in it.
* At present we only have one argument, the class name. Create an
* array to hold it.
*/
jclass stringClass;
jobjectArray strArray;
jstring classNameStr;
jstring startSystemServerStr;
//通过JNI查找java的java.lang.String类
stringClass = env->FindClass("java/lang/String");
assert(stringClass != NULL);
//创建字符串数组String strArray[] = new String[2];
strArray = env->NewObjectArray(2, stringClass, NULL);
assert(strArray != NULL);
//创建字符串classNameStr = new String("com.android.internal.os.ZygoteInit")
classNameStr = env->NewStringUTF(className);
assert(classNameStr != NULL);
//设置字符串数组元素strArray[0]="com.android.internal.os.ZygoteInit"
env->SetObjectArrayElement(strArray, 0, classNameStr);
//创建字符串startSystemServerStr= new String("true")
startSystemServerStr = env->NewStringUTF(startSystemServer ? "true" : "false");
//设置字符串数组元素strArray[1]="true"
env->SetObjectArrayElement(strArray, 1, startSystemServerStr);
/*
* Start VM. This thread becomes the main thread of the VM, and will
* not return until the VM exits.
*/
jclass startClass;
jmethodID startMeth;
//将字符串className 复制到slashClassName
slashClassName = strdup(className);
//为符合JNI规范,将com.android.internal.os.ZygoteInit中的.换成/,变为slashClassName = com/android/internal/os/ZygoteInit
for (cp = slashClassName; *cp != '\0'; cp++)
if (*cp == '.')
*cp = '/';
//查找Java类com/android/internal/os/ZygoteInit
startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
LOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
//找到ZygoteInit类的静态main方法的jMethodID
startMeth = env->GetStaticMethodID(startClass, "main","([Ljava/lang/String;)V");
if (startMeth == NULL) {
LOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
//通过JNI调用ZygoteInit类的main函数,传递的参数为:
//startClass = ZygoteInit
//startMeth = main
//strArray =["com.android.internal.os.ZygoteInit","true"]
//在调用ZygoteInit类的main方法后,zygote就进入了java世界
env->CallStaticVoidMethod(startClass, startMeth, strArray);
#if 0
if (env->ExceptionCheck())
threadExitUncaughtException(env);
#endif
}
}
LOGD("Shutting down VM\n");
if (mJavaVM->DetachCurrentThread() != JNI_OK)
LOGW("Warning: unable to detach main thread\n");
if (mJavaVM->DestroyJavaVM() != 0)
LOGW("Warning: VM did not shut down cleanly\n");
bail:
free(slashClassName);
}
这个函数的作用是启动Android系统运行时库,它主要做了三件事情:
一是调用函数startVM启动虚拟机;
二是调用函数startReg注册JNI方法;
三是调用了com.android.internal.os.ZygoteInit类的main函数;
4.AndroidRuntime.cpp 启动虚拟机
[java] view
plaincopy
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv)
{
int result = -1;
JavaVMInitArgs initArgs; //虚拟机初始化参数
JavaVMOption opt; //虚拟机选项
char propBuf[PROPERTY_VALUE_MAX];
char stackTraceFileBuf[PROPERTY_VALUE_MAX];
char dexoptFlagsBuf[PROPERTY_VALUE_MAX];
char enableAssertBuf[sizeof("-ea:")-1 + PROPERTY_VALUE_MAX];
char jniOptsBuf[sizeof("-Xjniopts:")-1 + PROPERTY_VALUE_MAX];
char heapsizeOptsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX];
char extraOptsBuf[PROPERTY_VALUE_MAX];
char* stackTraceFile = NULL;
bool checkJni = false;
bool checkDexSum = false;
bool logStdio = false;
enum {
kEMDefault,
kEMIntPortable,
kEMIntFast,
#if defined(WITH_JIT)
kEMJitCompiler,
#endif
} executionMode = kEMDefault;
property_get("dalvik.vm.checkjni", propBuf, ""); //读取"dalvik.vm.checkjni"属性值,“true” : “false”
if (strcmp(propBuf, "true") == 0) {
checkJni = true;
} else if (strcmp(propBuf, "false") != 0) {
/* property is neither true nor false; fall back on kernel parameter */
property_get("ro.kernel.android.checkjni", propBuf, "");
if (propBuf[0] == '1') {
checkJni = true;
}
}
property_get("dalvik.vm.execution-mode", propBuf, "");//读取"dalvik.vm.execution-mode"属性值,“int:portable” : “int:fast”: “int:jit”
if (strcmp(propBuf, "int:portable") == 0) {
executionMode = kEMIntPortable;
} else if (strcmp(propBuf, "int:fast") == 0) {
executionMode = kEMIntFast;
#if defined(WITH_JIT)
} else if (strcmp(propBuf, "int:jit") == 0) {
executionMode = kEMJitCompiler;
#endif
}
property_get("dalvik.vm.stack-trace-file", stackTraceFileBuf, "");//读取"dalvik.vm.stack-trace-file"属性值
property_get("dalvik.vm.check-dex-sum", propBuf, "");//读取"dalvik.vm.check-dex-sum"属性值,“true” : “false”
if (strcmp(propBuf, "true") == 0) {
checkDexSum = true;
}
property_get("log.redirect-stdio", propBuf, "");
if (strcmp(propBuf, "true") == 0) {
logStdio = true;
}
strcpy(enableAssertBuf, "-ea:");
property_get("dalvik.vm.enableassertions", enableAssertBuf+4, "");//读取"dalvik.vm.enableassertions"属性值
strcpy(jniOptsBuf, "-Xjniopts:");
property_get("dalvik.vm.jniopts", jniOptsBuf+10, "");//读取"dalvik.vm.jniopts"属性值
/* route exit() to our handler */
opt.extraInfo = (void*) runtime_exit; //设置退出函数
opt.optionString = "exit";
mOptions.add(opt);
/* route fprintf() to our handler */
opt.extraInfo = (void*) runtime_vfprintf;//设置打印输出函数
opt.optionString = "vfprintf";
mOptions.add(opt);
opt.extraInfo = NULL;
/* enable verbose; standard options are { jni, gc, class } */
//options[curOpt++].optionString = "-verbose:jni";
opt.optionString = "-verbose:gc";
mOptions.add(opt);
//options[curOpt++].optionString = "-verbose:class";
strcpy(heapsizeOptsBuf, "-Xmx");
property_get("dalvik.vm.heapsize", heapsizeOptsBuf+4, "16m");//读取"dalvik.vm.heapsize"属性值
//LOGI("Heap size: %s", heapsizeOptsBuf);
opt.optionString = heapsizeOptsBuf;
mOptions.add(opt);
/*
* Enable or disable dexopt features, such as bytecode verification and
* calculation of register maps for precise GC.
*/
property_get("dalvik.vm.dexopt-flags", dexoptFlagsBuf, "");//读取"dalvik.vm.dexopt-flags"属性值
if (dexoptFlagsBuf[0] != '\0') {
const char* opc;
const char* val;
opc = strstr(dexoptFlagsBuf, "v="); /* verification */
if (opc != NULL) {
switch (*(opc+2)) {
case 'n': val = "-Xverify:none"; break;
case 'r': val = "-Xverify:remote"; break;
case 'a': val = "-Xverify:all"; break;
default: val = NULL; break;
}
if (val != NULL) {
opt.optionString = val;
mOptions.add(opt);
}
}
opc = strstr(dexoptFlagsBuf, "o="); /* optimization */
if (opc != NULL) {
switch (*(opc+2)) {
case 'n': val = "-Xdexopt:none"; break;
case 'v': val = "-Xdexopt:verified"; break;
case 'a': val = "-Xdexopt:all"; break;
default: val = NULL; break;
}
if (val != NULL) {
opt.optionString = val;
mOptions.add(opt);
}
}
opc = strstr(dexoptFlagsBuf, "m=y"); /* register map */
if (opc != NULL) {
opt.optionString = "-Xgenregmap";
mOptions.add(opt);
/* turn on precise GC while we're at it */
opt.optionString = "-Xgc:precise";
mOptions.add(opt);
}
}
/* enable debugging; set suspend=y to pause during VM init */
#ifdef HAVE_ANDROID_OS
/* use android ADB transport */
opt.optionString ="-agentlib:jdwp=transport=dt_android_adb,suspend=n,server=y";
#else
/* use TCP socket; address=0 means start at port 8000 and probe up */
LOGI("Using TCP socket for JDWP\n");
opt.optionString ="-agentlib:jdwp=transport=dt_socket,suspend=n,server=y,address=0";
#endif
mOptions.add(opt);
char enableDPBuf[sizeof("-Xdeadlockpredict:") + PROPERTY_VALUE_MAX];
property_get("dalvik.vm.deadlock-predict", propBuf, "");
if (strlen(propBuf) > 0) {
strcpy(enableDPBuf, "-Xdeadlockpredict:");
strcat(enableDPBuf, propBuf);
opt.optionString = enableDPBuf;
mOptions.add(opt);
}
LOGD("CheckJNI is %s\n", checkJni ? "ON" : "OFF");
if (checkJni) {
/* extended JNI checking */
opt.optionString = "-Xcheck:jni";
mOptions.add(opt);
/* set a cap on JNI global references */
opt.optionString = "-Xjnigreflimit:2000";
mOptions.add(opt);
/* with -Xcheck:jni, this provides a JNI function call trace */
//opt.optionString = "-verbose:jni";
//mOptions.add(opt);
}
char lockProfThresholdBuf[sizeof("-Xlockprofthreshold:") + sizeof(propBuf)];
property_get("dalvik.vm.lockprof.threshold", propBuf, "");
if (strlen(propBuf) > 0) {
strcpy(lockProfThresholdBuf, "-Xlockprofthreshold:");
strcat(lockProfThresholdBuf, propBuf);
opt.optionString = lockProfThresholdBuf;
mOptions.add(opt);
}
#if defined(WITH_JIT)
/* Force interpreter-only mode for selected opcodes. Eg "1-0a,3c,f1-ff" */
char jitOpBuf[sizeof("-Xjitop:") + PROPERTY_VALUE_MAX];
property_get("dalvik.vm.jit.op", propBuf, "");
if (strlen(propBuf) > 0) {
strcpy(jitOpBuf, "-Xjitop:");
strcat(jitOpBuf, propBuf);
opt.optionString = jitOpBuf;
mOptions.add(opt);
}
/* Force interpreter-only mode for selected methods */
char jitMethodBuf[sizeof("-Xjitmethod:") + PROPERTY_VALUE_MAX];
property_get("dalvik.vm.jit.method", propBuf, "");
if (strlen(propBuf) > 0) {
strcpy(jitMethodBuf, "-Xjitmethod:");
strcat(jitMethodBuf, propBuf);
opt.optionString = jitMethodBuf;
mOptions.add(opt);
}
#endif
if (executionMode == kEMIntPortable) {
opt.optionString = "-Xint:portable";
mOptions.add(opt);
} else if (executionMode == kEMIntFast) {
opt.optionString = "-Xint:fast";
mOptions.add(opt);
#if defined(WITH_JIT)
} else if (executionMode == kEMJitCompiler) {
opt.optionString = "-Xint:jit";
mOptions.add(opt);
#endif
}
if (checkDexSum) {
/* perform additional DEX checksum tests */
opt.optionString = "-Xcheckdexsum";
mOptions.add(opt);
}
if (logStdio) {
/* convert stdout/stderr to log messages */
opt.optionString = "-Xlog-stdio";
mOptions.add(opt);
}
if (enableAssertBuf[4] != '\0') {
/* accept "all" to mean "all classes and packages" */
if (strcmp(enableAssertBuf+4, "all") == 0)
enableAssertBuf[3] = '\0';
LOGI("Assertions enabled: '%s'\n", enableAssertBuf);
opt.optionString = enableAssertBuf;
mOptions.add(opt);
} else {
LOGV("Assertions disabled\n");
}
if (jniOptsBuf[10] != '\0') {
LOGI("JNI options: '%s'\n", jniOptsBuf);
opt.optionString = jniOptsBuf;
mOptions.add(opt);
}
if (stackTraceFileBuf[0] != '\0') {
static const char* stfOptName = "-Xstacktracefile:";
stackTraceFile = (char*) malloc(strlen(stfOptName) +
strlen(stackTraceFileBuf) +1);
strcpy(stackTraceFile, stfOptName);
strcat(stackTraceFile, stackTraceFileBuf);
opt.optionString = stackTraceFile;
mOptions.add(opt);
}
/* extra options; parse this late so it overrides others */
property_get("dalvik.vm.extra-opts", extraOptsBuf, "");
parseExtraOpts(extraOptsBuf);
/* Set the properties for locale */
{
char langOption[sizeof("-Duser.language=") + 3];
char regionOption[sizeof("-Duser.region=") + 3];
strcpy(langOption, "-Duser.language=");
strcpy(regionOption, "-Duser.region=");
readLocale(langOption, regionOption);
opt.extraInfo = NULL;
opt.optionString = langOption;
mOptions.add(opt);
opt.optionString = regionOption;
mOptions.add(opt);
}
/*
* We don't have /tmp on the device, but we often have an SD card. Apps
* shouldn't use this, but some test suites might want to exercise it.
*/
opt.optionString = "-Djava.io.tmpdir=/sdcard";
mOptions.add(opt);
initArgs.version = JNI_VERSION_1_4;
initArgs.options = mOptions.editArray();
initArgs.nOptions = mOptions.size();
initArgs.ignoreUnrecognized = JNI_FALSE;
/*
* 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.
*调用JNI_CreateJavaVM函数创建虚拟机,关于虚拟机创建过程可参考dalvik\vm\Jni.c
*/
if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
LOGE("JNI_CreateJavaVM failed\n");
goto bail;
}
result = 0;
bail:
free(stackTraceFile);
return result;
}
5.AndroidRuntime.cpp 注册JNI函数
第4步中已经创建好了虚拟机,因此需要给该虚拟机注册一些JNI函数。
[java] view
plaincopy
int AndroidRuntime::startReg(JNIEnv* env)
{
/*
* 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.) 设置线程创建函数为javaCreateThreadEtc
*/
androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);
LOGV("--- 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.
*/
env->PushLocalFrame(200);
//注册JNI函数,所有的JNI函数存放在gRegJNI全局数组中
if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
env->PopLocalFrame(NULL);
return -1;
}
env->PopLocalFrame(NULL);
//createJavaThread("fubar", quickTest, (void*) "hello");
return 0;
}
[java] view
plaincopy
//JNI函数注册方法
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
LOGD("----------!!! %s failed to load\n", array[i].mName);
#endif
return -1;
}
}
return 0;
}
[html] view
plaincopy
//gRegJNI全局数组中
static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_debug_JNITest),
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_FloatMath),
REG_JNI(register_android_text_format_Time),
REG_JNI(register_android_pim_EventRecurrence),
REG_JNI(register_android_content_AssetManager),
REG_JNI(register_android_content_StringBlock),
REG_JNI(register_android_content_XmlBlock),
REG_JNI(register_android_emoji_EmojiFactory),
REG_JNI(register_android_security_Md5MessageDigest),
REG_JNI(register_android_text_AndroidCharacter),
REG_JNI(register_android_text_AndroidBidi),
REG_JNI(register_android_text_KeyCharacterMap),
REG_JNI(register_android_os_Process),
REG_JNI(register_android_os_Binder),
REG_JNI(register_android_view_Display),
REG_JNI(register_android_nio_utils),
REG_JNI(register_android_graphics_PixelFormat),
REG_JNI(register_android_graphics_Graphics),
REG_JNI(register_android_view_Surface),
REG_JNI(register_android_view_ViewRoot),
REG_JNI(register_com_google_android_gles_jni_EGLImpl),
REG_JNI(register_com_google_android_gles_jni_GLImpl),
REG_JNI(register_android_opengl_jni_GLES10),
REG_JNI(register_android_opengl_jni_GLES10Ext),
REG_JNI(register_android_opengl_jni_GLES11),
REG_JNI(register_android_opengl_jni_GLES11Ext),
REG_JNI(register_android_opengl_jni_GLES20),
REG_JNI(register_android_graphics_Bitmap),
REG_JNI(register_android_graphics_BitmapFactory),
REG_JNI(register_android_graphics_BitmapRegionDecoder),
REG_JNI(register_android_graphics_Camera),
REG_JNI(register_android_graphics_Canvas),
REG_JNI(register_android_graphics_ColorFilter),
REG_JNI(register_android_graphics_DrawFilter),
REG_JNI(register_android_graphics_Interpolator),
REG_JNI(register_android_graphics_LayerRasterizer),
REG_JNI(register_android_graphics_MaskFilter),
REG_JNI(register_android_graphics_Matrix),
REG_JNI(register_android_graphics_Movie),
REG_JNI(register_android_graphics_NinePatch),
REG_JNI(register_android_graphics_Paint),
REG_JNI(register_android_graphics_Path),
REG_JNI(register_android_graphics_PathMeasure),
REG_JNI(register_android_graphics_PathEffect),
REG_JNI(register_android_graphics_Picture),
REG_JNI(register_android_graphics_PorterDuff),
REG_JNI(register_android_graphics_Rasterizer),
REG_JNI(register_android_graphics_Region),
REG_JNI(register_android_graphics_Shader),
REG_JNI(register_android_graphics_Typeface),
REG_JNI(register_android_graphics_Xfermode),
REG_JNI(register_android_graphics_YuvImage),
REG_JNI(register_com_android_internal_graphics_NativeUtils),
REG_JNI(register_android_database_CursorWindow),
REG_JNI(register_android_database_SQLiteCompiledSql),
REG_JNI(register_android_database_SQLiteDatabase),
REG_JNI(register_android_database_SQLiteDebug),
REG_JNI(register_android_database_SQLiteProgram),
REG_JNI(register_android_database_SQLiteQuery),
REG_JNI(register_android_database_SQLiteStatement),
REG_JNI(register_android_os_Debug),
REG_JNI(register_android_os_FileObserver),
REG_JNI(register_android_os_FileUtils),
REG_JNI(register_android_os_MessageQueue),
REG_JNI(register_android_os_ParcelFileDescriptor),
REG_JNI(register_android_os_Power),
REG_JNI(register_android_os_StatFs),
REG_JNI(register_android_os_SystemProperties),
REG_JNI(register_android_os_UEventObserver),
REG_JNI(register_android_net_LocalSocketImpl),
REG_JNI(register_android_net_NetworkUtils),
REG_JNI(register_android_net_TrafficStats),
REG_JNI(register_android_net_wifi_WifiManager),
REG_JNI(register_android_nfc_NdefMessage),
REG_JNI(register_android_nfc_NdefRecord),
REG_JNI(register_android_os_MemoryFile),
REG_JNI(register_com_android_internal_os_ZygoteInit),
REG_JNI(register_android_hardware_Camera),
REG_JNI(register_android_hardware_SensorManager),
REG_JNI(register_android_media_AudioRecord),
REG_JNI(register_android_media_AudioSystem),
REG_JNI(register_android_media_AudioTrack),
REG_JNI(register_android_media_JetPlayer),
REG_JNI(register_android_media_ToneGenerator),
REG_JNI(register_android_opengl_classes),
REG_JNI(register_android_bluetooth_HeadsetBase),
REG_JNI(register_android_bluetooth_BluetoothAudioGateway),
REG_JNI(register_android_bluetooth_BluetoothSocket),
REG_JNI(register_android_bluetooth_ScoSocket),
REG_JNI(register_android_server_BluetoothService),
REG_JNI(register_android_server_BluetoothEventLoop),
REG_JNI(register_android_server_BluetoothA2dpService),
REG_JNI(register_android_server_Watchdog),
REG_JNI(register_android_message_digest_sha1),
REG_JNI(register_android_ddm_DdmHandleNativeHeap),
REG_JNI(register_android_backup_BackupDataInput),
REG_JNI(register_android_backup_BackupDataOutput),
REG_JNI(register_android_backup_FileBackupHelperBase),
REG_JNI(register_android_backup_BackupHelperDispatcher),
REG_JNI(register_android_hardware_fm_fmradio),
REG_JNI(register_android_app_NativeActivity),
REG_JNI(register_android_view_InputChannel),
REG_JNI(register_android_view_InputQueue),
REG_JNI(register_android_view_KeyEvent),
REG_JNI(register_android_view_MotionEvent),
REG_JNI(register_android_content_res_ObbScanner),
REG_JNI(register_android_content_res_Configuration),
};
6.ZygoteInit.java 调用了com.android.internal.os.ZygoteInit类的main函数
[java] view
plaincopy
public static void main(String argv[]) {
//传入的参数argv = ["com.android.internal.os.ZygoteInit","true"]
try {
//设置虚拟机的最小堆栈大小
VMRuntime.getRuntime().setMinimumHeapSize(5 * 1024 * 1024);
// Start profiling the zygote initialization.启动性能统计
SamplingProfilerIntegration.start();
//注册zygote等待客户端连接的socket
registerZygoteSocket();
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, SystemClock.uptimeMillis());
//预加载java类和资源
preloadClasses();
preloadResources();
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,SystemClock.uptimeMillis());
// Finish profiling the zygote initialization.结束统计并生成结果文件
SamplingProfilerIntegration.writeZygoteSnapshot();
// Do an initial gc to clean up after startup,执行垃圾回收
gc();
// If requested, start system server directly from Zygote
if (argv.length != 2) {
throw new RuntimeException(argv[0] + USAGE_STRING);
}
if (argv[1].equals("true")) {
//启动SystemServer进程
startSystemServer();
} else if (!argv[1].equals("false")) {
throw new RuntimeException(argv[0] + USAGE_STRING);
}
Log.i(TAG, "Accepting command socket connections");
//boolean ZYGOTE_FORK_MODE = false; 因此调用runSelectLoopMode()函数
if (ZYGOTE_FORK_MODE) {
runForkMode();
} else {
runSelectLoopMode();
}
closeServerSocket(); //关闭socket
} catch (MethodAndArgsCaller caller) {
//捕获SytemServer进程调用RuntimeInit.java 中zygoteInit函数抛出的MethodAndArgsCaller异常
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}
该main函数的作用:
<1>.调用registerZygoteSocket函数创建了一个socket接口,建立IPC通信的服务端;
<2> preloadClasses,preloadResources函数预加载类和资源
<2>.调用startSystemServer函数来启动SystemServer组件;
<3>.调用runSelectLoopMode函数进入一个无限循环在前面创建的socket接口上等待ActivityManagerService请求创建新的应用程序进程。
7.ZygoteInit.java 建立socket通信服务端
zygote 并没有采用binder通信机制,而是采用基于AF_UNIX类型的socket通信方式
[java] view
plaincopy
private static void registerZygoteSocket() {
if (sServerSocket == null) {
int fileDesc;
try {
//从环境变量中获取文件句柄,这个socket接口是通过文件描述符来创建的,这个文件描符代表的就是我们前面说的/dev/socket/zygote文件了。这个文件描述符是通过环境变量ANDROID_SOCKET_ENV得到的,关于socket的创建及环境变量的设置请参考init进程源码分析
String env = System.getenv(ANDROID_SOCKET_ENV);
fileDesc = Integer.parseInt(env);
} catch (RuntimeException ex) {
throw new RuntimeException(ANDROID_SOCKET_ENV + " unset or invalid", ex);
}
try {
//创建服务端socket,该socket将监听并接受客户端请求
sServerSocket = new LocalServerSocket(createFileDescriptor(fileDesc));
} catch (IOException ex) {
throw new RuntimeException("Error binding to local socket '" + fileDesc + "'", ex);
}
}
}
8.ZygoteInit.java 预加载类和资源
[java] view
plaincopy
private static void preloadClasses() {
final VMRuntime runtime = VMRuntime.getRuntime();
//通过反射机制获取输入流,类资源文件为"preloaded-clprr"
InputStream is = ZygoteInit.class.getClassLoader().getResourceAsStream(PRELOADED_CLASSES);
if (is == null) {
Log.e(TAG, "Couldn't find " + PRELOADED_CLASSES + ".");
} else {
Log.i(TAG, "Preloading classes...");
long startTime = SystemClock.uptimeMillis();
// Drop root perms while running static initializers.
//设置有效组ID和有效用户ID
setEffectiveGroup(UNPRIVILEGED_GID);
setEffectiveUser(UNPRIVILEGED_UID);
// Alter the target heap utilization. With explicit GCs this
// is not likely to have any effect.
float defaultUtilization = runtime.getTargetHeapUtilization();
runtime.setTargetHeapUtilization(0.8f);
// Start with a clean slate.
runtime.gcSoftReferences();
runtime.runFinalizationSync();
Debug.startAllocCounting();
try {
BufferedReader br= new BufferedReader(new InputStreamReader(is), 256);
int count = 0;
String line;
//一行一行读取文件内容
while ((line = br.readLine()) != null) {
// Skip comments and blank lines.
line = line.trim();
if (line.startsWith("#") || line.equals("")) {
continue;
}
try {
if (Config.LOGV) {
Log.v(TAG, "Preloading " + line + "...");
}
//通过Java反射机制加载类,每一行储存的是类名
Class.forName(line);
if (Debug.getGlobalAllocSize() > PRELOAD_GC_THRESHOLD) {
if (Config.LOGV) {
Log.v(TAG," GC at " + Debug.getGlobalAllocSize());
}
runtime.gcSoftReferences();
runtime.runFinalizationSync();
Debug.resetGlobalAllocSize();
}
count++;
} catch (ClassNotFoundException e) {
Log.w(TAG, "Class not found for preloading: " + line);
} catch (Throwable t) {
Log.e(TAG, "Error preloading " + line + ".", t);
if (t instanceof Error) {
throw (Error) t;
}
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
}
throw new RuntimeException(t);
}
}
Log.i(TAG, "...preloaded " + count + " classes in "
+ (SystemClock.uptimeMillis()-startTime) + "ms.");
} catch (IOException e) {
Log.e(TAG, "Error reading " + PRELOADED_CLASSES + ".", e);
} finally {
// Restore default.
runtime.setTargetHeapUtilization(defaultUtilization);
Debug.stopAllocCounting();
// Bring back root. We'll need it later.
setEffectiveUser(ROOT_UID);
setEffectiveGroup(ROOT_GID);
}
}
}
preloadClasses 执行时间比较长,也是导致android系统启动慢的原因。
加载共享资源
[java] view
plaincopy
private static void preloadResources() {
final VMRuntime runtime = VMRuntime.getRuntime();
Debug.startAllocCounting();
try {
runtime.gcSoftReferences();
runtime.runFinalizationSync();
mResources = Resources.getSystem();
mResources.startPreloading();
if (PRELOAD_RESOURCES) {
Log.i(TAG, "Preloading resources...");
long startTime = SystemClock.uptimeMillis();
TypedArray ar = mResources.obtainTypedArray(com.android.internal.R.array.preloaded_drawables);
int N = preloadDrawables(runtime, ar);
Log.i(TAG, "...preloaded " + N + " resources in "+ (SystemClock.uptimeMillis()-startTime) + "ms.");
startTime = SystemClock.uptimeMillis();
ar = mResources.obtainTypedArray(
com.android.internal.R.array.preloaded_color_state_lists);
N = preloadColorStateLists(runtime, ar);
Log.i(TAG, "...preloaded " + N + " resources in "+ (SystemClock.uptimeMillis()-startTime) + "ms.");
}
mResources.finishPreloading();
} catch (RuntimeException e) {
Log.w(TAG, "Failure preloading resources", e);
} finally {
Debug.stopAllocCounting();
}
}
9.ZygoteInit.java 启动SystemServer
[java] view
plaincopy
private static boolean startSystemServer()
throws MethodAndArgsCaller, RuntimeException {
/* Hardcoded command line to start the system server */
String args[] = {
"--setuid=1000",
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,3001,3002,3003",
"--capabilities=130104352,130104352",
"--runtime-init",
"--nice-name=system_server",
"com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs = null;
int pid;
try {
parsedArgs = new ZygoteConnection.Arguments(args); //把字符串数组中的参数转换为Arguments对象
/*
* Enable debugging of the system process if *either* the command line flags
* indicate it should be debuggable or the ro.debuggable system property
* is set to "1"
*/
int debugFlags = parsedArgs.debugFlags;
if ("1".equals(SystemProperties.get("ro.debuggable")))
debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
/* fork一个子进程作为SystemServer进程*/
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids, debugFlags, null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
/* For child process */
if (pid == 0) {
//SystemServer进程的初始化设置
handleSystemServerProcess(parsedArgs);
}
return true;
}
Zygote进程通过Zygote.forkSystemServer函数来创建一个新的进程来启动SystemServer组件,返回值pid等0的地方就是新的进程要执行的路径,即新创建的进程会执行handleSystemServerProcess函数。
10.ZygoteInit.java 循环等待客户端的连接
[java] view
plaincopy
private static void runSelectLoopMode() throws MethodAndArgsCaller {
ArrayList<FileDescriptor> fds = new ArrayList(); //存储所有客户端连接的socket文件句柄
ArrayList<ZygoteConnection> peers = new ArrayList();//存储所有客户端连接
FileDescriptor[] fdArray = new FileDescriptor[4];
fds.add(sServerSocket.getFileDescriptor());//保存先前创建用于等待客户端连接的服务端socket
peers.add(null);
int loopCount = GC_LOOP_COUNT;
while (true) {
int index;
/*
* Call gc() before we block in select().
* It's work that has to be done anyway, and it's better
* to avoid making every child do it. It will also
* madvise() any free memory as a side-effect.
*
* Don't call it every time, because walking the entire
* heap is a lot of overhead to free a few hundred bytes.
*/
if (loopCount <= 0) {
gc();
loopCount = GC_LOOP_COUNT;
} else {
loopCount--;
}
try {
fdArray = fds.toArray(fdArray);
//selectReadable内部调用select,使用多路复用I/O模型
//当有客户端连接时,selectReadable返回
index = selectReadable(fdArray);
} catch (IOException ex) {
throw new RuntimeException("Error in select()", ex);
}
if (index < 0) {
throw new RuntimeException("Error in select()");
} else if (index == 0) {
//有一个客户端连接
ZygoteConnection newPeer = acceptCommandPeer();
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
boolean done;
//客户端发送了请求,peers.get(index)获取当前客户端的ZygoteConnection,并调用当前连接的runOnce()函数创建新的应用程序
done = peers.get(index).runOnce();
if (done) {
peers.remove(index);
fds.remove(index);
}
}
}
}
zygote总结:
1.创建AppRuntime对象,并调用它的start函数;
2.调用startVm创建Java虚拟机;
3.调用startReg函数来注册JNI函数;
4.调用ZygoteInit类的main函数,从此就进入了Java世界;
5.调用registerZygoteSocket 注册一个服务端socket;
6.调用preloadClasses 函数加载类资源;
7.调用preloadResources函数加载系统资源;
8.调用startSystemServer函数创建SystemServer进程;
9.调用runSelectLoopMode函数进入服务端socket监听;
相关文章推荐
- Zygote进程启动过程源代码分析
- Android系统进程Zygote启动过程的源代码分析
- Android系统进程Zygote启动过程的源代码分析
- Android系统进程Zygote启动过程的源代码分析(1)
- Android系统进程Zygote启动过程的源代码分析
- Android系统进程Zygote启动过程的源代码分析
- Zygote进程启动过程源代码分析
- Android系统进程Zygote启动过程的源代码分析
- Android系统进程Zygote启动过程的源代码分析(2)
- Android系统进程Zygote启动过程的源代码分析
- Android系统进程Zygote启动过程的源代码分析(3)
- Android系统进程Zygote启动过程的源代码分析
- Android系统进程Zygote启动过程的源代码分析
- Android系统进程Zygote启动过程的源代码分析
- Android系统进程Zygote启动过程的源代码分析
- Android系统进程Zygote启动过程的源代码分析
- zygote进程启动过程源代码分析 (good)
- Android系统进程Zygote启动过程的源代码分析
- Android系统进程Zygote启动过程的源代码分析
- Android系统进程Zygote启动过程的源代码分析