为什么将Zygote叫做受精卵呢?是因为在Android系统中,所有的应用程序进程以及系统服务进程SystemServer都是由Zygote进程孕育(fork)出来的。
Android应用程序是由java语言编写的,运行于各自独立的Dalvik虚拟机中。那么Android的处理机制是什么呢?Android首先创建一个Zygote虚拟机,然后通过它孵化出其他的虚拟机进程,进而共享虚拟机内存和框架层资源,这样大幅度提高了应用程序启动和运行速度。
zygote是在init.rc中定义的守护进程服务(Daemon Service),在Android5.0中,Zygote的启动发生了一些变化,以前直接放在init.rc中的代码块放到了单独的文件中,在init.rc中通过import的方式引入文件,如下:
import /init.${ro.zygote}.rc
从上面的语句可以看出,init.rc并不是直接引入某个固定的文件,而是根据属性“ro.zygote”的内容来引入不同的文件。这是因为Android从5.0开始,Android开始支持64位的编译,Zygote本身也会有32位和64位版本的区别,因此,这里通过ro.zygote属性来控制启动不同版本的Zygote进程。该文件位于system/core/init/下,目录下有Init.zygote64.rc,Init.zygote32.rc,Init.zygote32_64.rc,Init.zygot64_32.rc,至于调用哪个是由硬件决定的,这里以Init.zygote64_32.rc为例,代码如下:
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
class main #class是一个Option,指定zygote服务的类型是main
socket zygote stream 660 root system #socket是一个Option,创建一个Socket名为dev/socket/zygote,Socket类型是stream,权限为660
onrestart write /sys/android_power/request_state wake #onrestart是一个Option,设置zygote重启时需要执行的Command
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin--zygote --socket-name=zygote_secondary
class main
socket zygote_secondary stream 660 root system
onrestart restart zygote
从代码中我们可以看出,系统定义了两个Zygote服务:zygote和zygote_secondary。这两个服务最大的区别是启动的可执行文件不同,一个是app_process64,另一个是app_process32。由关键字service告诉init进程创建一个名为“zygote”的进程,这个zygote进程要执行的程序是/system/bin/app_process64(可执行文件),给这个zygote进程传递了5个参数,分别是-Xzygote,/system/bin,--zygote,--start-system-server,--socket-name=zygote;另外zygote服务需要开启一个Socket,并且zygote重启时,需要执行下面的命令:
修改/sys/android_power/request_state;修改/sys/power/state;重启media;重启netd。
我们先看下Zygote进程的初始化过程,如下:
从上面的分析中可以看出zygote要执行的程序是/system/bin/app_process,它的源码位于frameworks/base/cmds/app_process/App_main.cpp文件中,入口函数是main。
main函数的主要功能是解析启动参数。
在源码中提供了app_process的启动方式,参数如下:
app_process [java-options(虚拟机参数)] cmd-dir(运行目录) start-calss-name(java类) [options(参数)]
[java-options]:指定启动dalvik虚拟机时传递给虚拟机的参数,以“-”开头;
cmd-dir:要运行的进程所在的目录,通常是/system/bin;
start-class-name:指定要加载到虚拟机的类,而后调用其main方法;使用参数“--zygote”时会直接执行ZygoteInit类。
[options]:指定传递给类的参数;以符号“--”开头。参数“--zygote”表示要启动zygote进程。参数“--application”表示要以普通进程的方式执行java代码。
我们看下App_main中main函数的代码,AppRuntime是在app_process中定义的类,继承了系统的AndroidRuntime类。AndroidRuntime类的主要作用是创建和初始化虚拟机。
int main(int argc, char* const argv[])
{
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
// Older kernels don't understand PR_SET_NO_NEW_PRIVS and return
// EINVAL. Don't die on such kernels.
if (errno != EINVAL) {
LOG_ALWAYS_FATAL("PR_SET_NO_NEW_PRIVS failed: %s", strerror(errno));
return 12;
}
}
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
// Process command line arguments
// ignore argv[0]
argc--;
argv++; /* 因为argv[0]不是参数,所以忽略argv[0],并将argc减1*/
// 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.
int i;
for (i = 0; i < argc; i++) {
if (argv[i][0] != '-') {
break;
}
if (argv[i][1] == '-' && argv[i][2] == 0) {
++i; // Skip --.
break;
}
runtime.addOption(strdup(argv[i]));
}
// Parse runtime arguments. Stop at first unrecognized option.
bool zygote = false;
bool startSystemServer = false;
bool application = false;
String8 niceName;
String8 className;
++i; // Skip unused "parent dir" argument.
while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) { /* 如果参数中指定了--zygote,则启动zygote,niceName设置为“zygote” */
zygote = true;
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true; /* 是否启动System Server */
} else if (strcmp(arg, "--application") == 0) {
application = true; /* 是否启动application */
} else if (strncmp(arg, "--nice-name=", 12) == 0) {
niceName.setTo(arg + 12); /* 是否指定了nice name */
} else if (strncmp(arg, "--", 2) != 0) {
className.setTo(arg);
break;
} else {
--i;
break;
}
}
Vector 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"));//非zygote模式
runtime.setClassNameAndArgs(className, argc - i, argv + i);
} else {
// We're in zygote mode.
maybeCreateDalvikCache();
if (startSystemServer) {
args.add(String8("start-system-server"));
}
char prop[PROP_VALUE_MAX];
if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
ABI_LIST_PROPERTY);
return 11;
}
String8 abiFlag("--abi-list=");
abiFlag.append(prop);
args.add(abiFlag);
// In zygote mode, pass all remaining arguments to the zygote
// main() method.
for (; i < argc; ++i) {
args.add(String8(argv[i]));
}
}
if (!niceName.isEmpty()) {
runtime.setArgv0(niceName.string());
set_process_name(niceName.string());/* 根据nicename调用系统函数prctl,open,write修改进程名,由于启动过程中指定了--zygote参数,所以这里的进程名是zygote */
}
/* if-else用于匹配两种启动类型,启动zygote或者是启动application */
if (zygote) { /* 如果参数中指定了--zygote,则启动zygote */
runtime.start("com.android.internal.os.ZygoteInit", args);
} else if (className) { /* 启动应用程序 */
runtime.start("com.android.internal.os.RuntimeInit", args);
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
return 10;
}
}
从App_main的main函数中可以看出调用AppRuntime的start方法启动ZygoteInit。
AppRuntime的实现代码位于frameworks\base\cmds\app_process\App_main.cpp中,它是AndroidRuntime的派生类,其start方法便是继承自AndroidRuntime。
AndroidRuntime负责开启Android运行时环境,代码位于framewroks\base\core\jni\AndroidRuntime.cpp,定位到start方法,代码如下:
/*
* Start the Android runtime. This involves starting the virtual machine
* and calling the "static void main(String[] args)" method in the class
* named by "className".
*
* Passes the main function two arguments, the class name and the specified
* options string.
*/
/* 根据上面的分析,init.rc中指定了参数--zygote,那么传入到这个函数的参数分别是:classname=“com.android.internal.os.ZygoteInit;options=start-system-server” */
void AndroidRuntime::start(const char* className, const Vector& options)
{
ALOGD(">>>>>> START %s uid %d <<<<<<\n",
className != NULL ? className : "(unknown)", getuid());
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");
//ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);
/* start the virtual machine 开启虚拟机*/
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
if (startVm(&mJavaVM, &env) != 0) {
return;
}
/* 开启虚拟机后执行的工作,这里是空函数体,什么都没做。运行时实际调用的是AppRuntime的onVmCreated函数,保存了类的全局引用。*/
onVmCreated(env);
/*
* Register android functions.注册Android 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.调用指定类的main函数,并传入参数classname和options。在这之前需要将参数classname和options通过JNI函数转化为JAVA可识别的参数类型。
*/
jclass stringClass;
jobjectArray strArray;
jstring classNameStr; /* 用于转换classname为java可识别类型的字符串 */
stringClass = env->FindClass("java/lang/String");
assert(stringClass != NULL);
strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);/* 调用JNI函数生成一个对象数组,数组大小为options.size()+1(这里为2,只有一个参数start-system-server),存放字符串类型的元素 */
assert(strArray != NULL);
classNameStr = env->NewStringUTF(className);
assert(classNameStr != NULL);
env->SetObjectArrayElement(strArray, 0, classNameStr); /* 将转化后的classname存入数组 */
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);/* 将转化后的options存入数组 */
}
/*
* Start VM. This thread becomes the main thread of the VM, and will
* not return until the VM exits.
*/
/* 将classname转化为slash格式的字符串,以符合JNI的命名规则。这里将com.android.internal.os.ZygoteInit转化为com/android/internal/os/ZygoteInit,用于通过JNI函数findClass找到这个JAVA类。 */
char* slashClassName = toSlashClassName(className);
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
/* 得到指定类ZygoteInit的main方法的方法ID */
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 {
/* 通过调用JNI函数CallStaticVoidMethod调用JAVA类ZygoteInit的main方法,并传入参数com.android.internal.os.ZygoteInit和参数true */
env->CallStaticVoidMethod(startClass, startMeth, strArray);
#if 0
if (env->ExceptionCheck())
threadExitUncaughtException(env);
#endif
}
}
free(slashClassName);/* 将转化后的classname存入数组 */
/* detach当前线程,释放JNI资源并关闭虚拟机 */
ALOGD("Shutting down VM\n");
if (mJavaVM->DetachCurrentThread() != JNI_OK)
ALOGW("Warning: unable to detach main thread\n");
if (mJavaVM->DestroyJavaVM() != 0)
ALOGW("Warning: VM did not shut down cleanly\n");
}
AndroidRuntime的start方法开启了Android运行时,start方法主要做了三部分工作:
1、创建Dalvik虚拟机
首先分析start工作的第一步,Dalvik虚拟机是调用startVM函数创建的,该函数位于AndroidRuntime.cpp中。代码如下:
/*
* Start the Dalvik Virtual Machine.
*
* Various arguments, most determined by system properties, are passed in.
* The "mOptions" vector is updated.
*
* CAUTION: when adding options in here, be careful not to put the
* char buffer inside a nested scope. Adding the buffer to the
* options using mOptions.add() does not copy the buffer, so if the
* buffer goes out of scope the option may be overwritten. It's best
* to put the buffer at the top of the function so that it is more
* unlikely that someone will surround it in a scope at a later time
* and thus introduce a bug.
*
* Returns 0 on success.
*/
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv)
{
int result = -1;
JavaVMInitArgs initArgs;
char propBuf[PROPERTY_VALUE_MAX];/* 虚拟机的配置参数 */
char stackTraceFileBuf[sizeof("-Xstacktracefile:")-1 + 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 heapstartsizeOptsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];
char heapsizeOptsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX];
char heapgrowthlimitOptsBuf[sizeof("-XX:HeapGrowthLimit=")-1 + PROPERTY_VALUE_MAX];
char heapminfreeOptsBuf[sizeof("-XX:HeapMinFree=")-1 + PROPERTY_VALUE_MAX];
char heapmaxfreeOptsBuf[sizeof("-XX:HeapMaxFree=")-1 + PROPERTY_VALUE_MAX];
char gctypeOptsBuf[sizeof("-Xgc:")-1 + PROPERTY_VALUE_MAX];
char backgroundgcOptsBuf[sizeof("-XX:BackgroundGC=")-1 + PROPERTY_VALUE_MAX];
char heaptargetutilizationOptsBuf[sizeof("-XX:HeapTargetUtilization=")-1 + PROPERTY_VALUE_MAX];
char jitcodecachesizeOptsBuf[sizeof("-Xjitcodecachesize:")-1 + PROPERTY_VALUE_MAX];
char dalvikVmLibBuf[PROPERTY_VALUE_MAX];
char dex2oatXmsImageFlagsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];
char dex2oatXmxImageFlagsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX];
char dex2oatXmsFlagsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];
char dex2oatXmxFlagsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX];
char dex2oatCompilerFilterBuf[sizeof("--compiler-filter=")-1 + PROPERTY_VALUE_MAX];
char dex2oatImageCompilerFilterBuf[sizeof("--compiler-filter=")-1 + PROPERTY_VALUE_MAX];
char dex2oatFlagsBuf[PROPERTY_VALUE_MAX];
char dex2oatImageFlagsBuf[PROPERTY_VALUE_MAX];
char extraOptsBuf[PROPERTY_VALUE_MAX];
char voldDecryptBuf[PROPERTY_VALUE_MAX];
enum {
kEMDefault,
kEMIntPortable,
kEMIntFast,
kEMJitCompiler,
} executionMode = kEMDefault;
char profilePeriod[sizeof("-Xprofile-period:")-1 + PROPERTY_VALUE_MAX];
char profileDuration[sizeof("-Xprofile-duration:")-1 + PROPERTY_VALUE_MAX];
char profileInterval[sizeof("-Xprofile-interval:")-1 + PROPERTY_VALUE_MAX];
char profileBackoff[sizeof("-Xprofile-backoff:")-1 + PROPERTY_VALUE_MAX];
char profileTopKThreshold[sizeof("-Xprofile-top-k-threshold:")-1 + PROPERTY_VALUE_MAX];
char profileTopKChangeThreshold[sizeof("-Xprofile-top-k-change-threshold:")-1 +
PROPERTY_VALUE_MAX];
char profileType[sizeof("-Xprofile-type:")-1 + PROPERTY_VALUE_MAX];
char profileMaxStackDepth[sizeof("-Xprofile-max-stack-depth:")-1 + PROPERTY_VALUE_MAX];
char langOption[sizeof("-Duser.language=") + 3];
char regionOption[sizeof("-Duser.region=") + 3];
char lockProfThresholdBuf[sizeof("-Xlockprofthreshold:")-1 + PROPERTY_VALUE_MAX];
char jitOpBuf[sizeof("-Xjitop:")-1 + PROPERTY_VALUE_MAX];
char jitMethodBuf[sizeof("-Xjitmethod:")-1 + PROPERTY_VALUE_MAX];
char nativeBridgeLibrary[sizeof("-XX:NativeBridge=") + PROPERTY_VALUE_MAX];
/* 通过属性系统获得dalvik.vm.checkjni的配置参数,checkjni是开发阶段一个非常重要的属性
* 通过它可以对JNI调用参数进行自动检查,还可以定位一些JNI产生的异常,比如JNI内存泄露。
* 如果checkjni设置为true,JNI调用过程就可以由dalvikvm记录并显示在logcat上。
* JNI检查会大幅度降低性能,只能在eng或userDebug版本上进行配置。 */
bool checkJni = false;
property_get("dalvik.vm.checkjni", propBuf, "");
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;
}
}
ALOGD("CheckJNI is %s\n", checkJni ? "ON" : "OFF");
if (checkJni) {
/* extended JNI checking 选项“-Xcheck:jni”,用来启动JNI方法检查。*/
addOption("-Xcheck:jni");
/* set a cap on JNI global references,设定JNI全局引用的个数不能超过2000 */
addOption("-Xjnigreflimit:2000");
/* with -Xcheck:jni, this provides a JNI function call trace */
//addOption("-verbose:jni");
}
/* 指定虚拟机的执行模式,Dalvik虚拟机支持三种运行模式,分别为Portable、Fast、Jit */
property_get("dalvik.vm.execution-mode", propBuf, "");
if (strcmp(propBuf, "int:portable") == 0) {
executionMode = kEMIntPortable;/* Dalvik虚拟机以可移植的方式进行编译,即编译出来的虚拟机可以在任何平台上运行 */
} else if (strcmp(propBuf, "int:fast") == 0) {
executionMode = kEMIntFast;/* Fast是针对当前平台对Dalvik虚拟机进行编译,这样编译出来的Dalvik虚拟机可以进行特殊的优化,从而使得它能更快的运行程序 */
} else if (strcmp(propBuf, "int:jit") == 0) {
executionMode = kEMJitCompiler;/* Jit不是解释执行代码,二是将代码动态编译成本地语言后再执行 */
}
/* -Xstacktracefile:用来指定调用堆栈输出文件。
* 当虚拟机收到SIGQUIT(Ctrl-\或者kill -3)信号时,会将所有线程的堆栈信息写入指定文件。
* 可以通过dalvik.vm.stack-trace-file系统属性来指定调用堆栈输出文件。
* 这样可以保留异常发生时的现场,方便调试定位出错原因。*/
parseRuntimeOption("dalvik.vm.stack-trace-file", stackTraceFileBuf, "-Xstacktracefile:");
/* 对优化过的DEX文件进行检测的配置参数,关闭后会提升性能,但如果文件损坏会导致虚拟机崩溃。 */
property_get("dalvik.vm.check-dex-sum", propBuf, "");
if (strcmp(propBuf, "true") == 0) {
/* perform additional DEX checksum tests */
addOption("-Xcheckdexsum");
}
property_get("log.redirect-stdio", propBuf, "");
if (strcmp(propBuf, "true") == 0) {
/* convert stdout/stderr to log messages */
addOption("-Xlog-stdio");
}
/* 设置是否支持java的断言表达式 */
strcpy(enableAssertBuf, "-ea:");
property_get("dalvik.vm.enableassertions", enableAssertBuf+sizeof("-ea:")-1, "");
if (enableAssertBuf[sizeof("-ea:")-1] != '\0') {
/* accept "all" to mean "all classes and packages" */
if (strcmp(enableAssertBuf+sizeof("-ea:")-1, "all") == 0)
enableAssertBuf[3] = '\0'; // truncate to "-ea"
ALOGI("Assertions enabled: '%s'\n", enableAssertBuf);
addOption(enableAssertBuf);
} else {
ALOGV("Assertions disabled\n");
}
strcpy(jniOptsBuf, "-Xjniopts:");
if (parseRuntimeOption("dalvik.vm.jniopts", jniOptsBuf, "-Xjniopts:")) {
ALOGI("JNI options: '%s'\n", jniOptsBuf);
}
/* route exit() to our handler */
addOption("exit", (void*) runtime_exit);
/* route fprintf() to our handler */
addOption("vfprintf", (void*) runtime_vfprintf);
/* register the framework-specific "is sensitive thread" hook */
addOption("sensitiveThread", (void*) runtime_isSensitiveThread);
/* enable verbose; standard options are { jni, gc, class } */
//addOption("-verbose:jni");
addOption("-verbose:gc");
//addOption("-verbose:class");
/*
* The default starting and maximum size of the heap. Larger
* values should be specified in a product property override.
* 设置虚拟机heap的大小,包括启动值(heapstartsize)和最大值(heapsize)*/
parseRuntimeOption("dalvik.vm.heapstartsize", heapstartsizeOptsBuf, "-Xms", "4m");
parseRuntimeOption("dalvik.vm.heapsize", heapsizeOptsBuf, "-Xmx", "16m");
// Increase the main thread's interpreter stack size for bug 6315322.
addOption("-XX:mainThreadStackSize=24K");
// Set the max jit code cache size. Note: size of 0 will disable the JIT.
parseRuntimeOption("dalvik.vm.jit.codecachesize",
jitcodecachesizeOptsBuf,
"-Xjitcodecachesize:");
parseRuntimeOption("dalvik.vm.heapgrowthlimit", heapgrowthlimitOptsBuf, "-XX:HeapGrowthLimit=");
parseRuntimeOption("dalvik.vm.heapminfree", heapminfreeOptsBuf, "-XX:HeapMinFree=");
parseRuntimeOption("dalvik.vm.heapmaxfree", heapmaxfreeOptsBuf, "-XX:HeapMaxFree=");
parseRuntimeOption("dalvik.vm.heaptargetutilization",
heaptargetutilizationOptsBuf,
"-XX:HeapTargetUtilization=");
property_get("ro.config.low_ram", propBuf, "");
if (strcmp(propBuf, "true") == 0) {
addOption("-XX:LowMemoryMode");
}
parseRuntimeOption("dalvik.vm.gctype", gctypeOptsBuf, "-Xgc:");
parseRuntimeOption("dalvik.vm.backgroundgctype", backgroundgcOptsBuf, "-XX:BackgroundGC=");
/*
* Enable or disable dexopt features, such as bytecode verification and
* calculation of register maps for precise GC.
*/
property_get("dalvik.vm.dexopt-flags", dexoptFlagsBuf, "");
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) {
addOption(val);
}
}
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;
case 'f': val = "-Xdexopt:full"; break;
default: val = NULL; break;
}
if (val != NULL) {
addOption(val);
}
}
opc = strstr(dexoptFlagsBuf, "m=y"); /* register map */
if (opc != NULL) {
addOption("-Xgenregmap");
/* turn on precise GC while we're at it */
addOption("-Xgc:precise");
}
}
/* enable debugging; set suspend=y to pause during VM init */
/* use android ADB transport */
addOption("-agentlib:jdwp=transport=dt_android_adb,suspend=n,server=y");
parseRuntimeOption("dalvik.vm.lockprof.threshold",
lockProfThresholdBuf,
"-Xlockprofthreshold:");
/* Force interpreter-only mode for selected opcodes. Eg "1-0a,3c,f1-ff" */
parseRuntimeOption("dalvik.vm.jit.op", jitOpBuf, "-Xjitop:");
/* Force interpreter-only mode for selected methods */
parseRuntimeOption("dalvik.vm.jit.method", jitMethodBuf, "-Xjitmethod:");
if (executionMode == kEMIntPortable) {
addOption("-Xint:portable");
} else if (executionMode == kEMIntFast) {
addOption("-Xint:fast");
} else if (executionMode == kEMJitCompiler) {
addOption("-Xint:jit");
}
// libart tolerates libdvm flags, but not vice versa, so only pass some options if libart.
property_get("persist.sys.dalvik.vm.lib.2", dalvikVmLibBuf, "libart.so");
bool libart = (strncmp(dalvikVmLibBuf, "libart", 6) == 0);
if (libart) {
// If we booting without the real /data, don't spend time compiling.
property_get("vold.decrypt", voldDecryptBuf, "");
bool skip_compilation = ((strcmp(voldDecryptBuf, "trigger_restart_min_framework") == 0) ||
(strcmp(voldDecryptBuf, "1") == 0));
// Extra options for boot.art/boot.oat image generation.
parseCompilerRuntimeOption("dalvik.vm.image-dex2oat-Xms", dex2oatXmsImageFlagsBuf,
"-Xms", "-Ximage-compiler-option");
parseCompilerRuntimeOption("dalvik.vm.image-dex2oat-Xmx", dex2oatXmxImageFlagsBuf,
"-Xmx", "-Ximage-compiler-option");
if (skip_compilation) {
addOption("-Ximage-compiler-option");
addOption("--compiler-filter=verify-none");
} else {
parseCompilerOption("dalvik.vm.image-dex2oat-filter", dex2oatImageCompilerFilterBuf,
"--compiler-filter=", "-Ximage-compiler-option");
}
// Make sure there is a preloaded-classes file.
if (!hasFile("/system/etc/preloaded-classes")) {
ALOGE("Missing preloaded-classes file, /system/etc/preloaded-classes not found: %s\n",
strerror(errno));
goto bail;
}
addOption("-Ximage-compiler-option");
addOption("--image-classes=/system/etc/preloaded-classes");
// If there is a compiled-classes file, push it.
if (hasFile("/system/etc/compiled-classes")) {
addOption("-Ximage-compiler-option");
addOption("--compiled-classes=/system/etc/compiled-classes");
}
property_get("dalvik.vm.image-dex2oat-flags", dex2oatImageFlagsBuf, "");
parseExtraOpts(dex2oatImageFlagsBuf, "-Ximage-compiler-option");
// Extra options for DexClassLoader.
parseCompilerRuntimeOption("dalvik.vm.dex2oat-Xms", dex2oatXmsFlagsBuf,
"-Xms", "-Xcompiler-option");
parseCompilerRuntimeOption("dalvik.vm.dex2oat-Xmx", dex2oatXmxFlagsBuf,
"-Xmx", "-Xcompiler-option");
if (skip_compilation) {
addOption("-Xcompiler-option");
addOption("--compiler-filter=verify-none");
} else {
parseCompilerOption("dalvik.vm.dex2oat-filter", dex2oatCompilerFilterBuf,
"--compiler-filter=", "-Xcompiler-option");
}
property_get("dalvik.vm.dex2oat-flags", dex2oatFlagsBuf, "");
parseExtraOpts(dex2oatFlagsBuf, "-Xcompiler-option");
}
/* extra options; parse this late so it overrides others */
property_get("dalvik.vm.extra-opts", extraOptsBuf, "");
parseExtraOpts(extraOptsBuf, NULL);
/* Set the properties for locale */
{
strcpy(langOption, "-Duser.language=");
strcpy(regionOption, "-Duser.region=");
readLocale(langOption, regionOption);
addOption(langOption);
addOption(regionOption);
}
/*
* Set profiler options
*/
if (libart) {
// Whether or not the profiler should be enabled.
property_get("dalvik.vm.profiler", propBuf, "0");
if (propBuf[0] == '1') {
addOption("-Xenable-profiler");
}
// Whether the profile should start upon app startup or be delayed by some random offset
// (in seconds) that is bound between 0 and a fixed value.
property_get("dalvik.vm.profile.start-immed", propBuf, "0");
if (propBuf[0] == '1') {
addOption("-Xprofile-start-immediately");
}
// Number of seconds during profile runs.
parseRuntimeOption("dalvik.vm.profile.period-secs", profilePeriod, "-Xprofile-period:");
// Length of each profile run (seconds).
parseRuntimeOption("dalvik.vm.profile.duration-secs",
profileDuration,
"-Xprofile-duration:");
// Polling interval during profile run (microseconds).
parseRuntimeOption("dalvik.vm.profile.interval-us", profileInterval, "-Xprofile-interval:");
// Coefficient for period backoff. The the period is multiplied
// by this value after each profile run.
parseRuntimeOption("dalvik.vm.profile.backoff-coeff", profileBackoff, "-Xprofile-backoff:");
// Top K% of samples that are considered relevant when
// deciding if the app should be recompiled.
parseRuntimeOption("dalvik.vm.profile.top-k-thr",
profileTopKThreshold,
"-Xprofile-top-k-threshold:");
// The threshold after which a change in the structure of the
// top K% profiled samples becomes significant and triggers
// recompilation. A change in profile is considered
// significant if X% (top-k-change-threshold) of the top K%
// (top-k-threshold property) samples has changed.
parseRuntimeOption("dalvik.vm.profile.top-k-ch-thr",
profileTopKChangeThreshold,
"-Xprofile-top-k-change-threshold:");
// Type of profile data.
parseRuntimeOption("dalvik.vm.profiler.type", profileType, "-Xprofile-type:");
// Depth of bounded stack data
parseRuntimeOption("dalvik.vm.profile.stack-depth",
profileMaxStackDepth,
"-Xprofile-max-stack-depth:");
// Native bridge library. "0" means that native bridge is disabled.
property_get("ro.dalvik.vm.native.bridge", propBuf, "");
if (propBuf[0] == '\0') {
ALOGW("ro.dalvik.vm.native.bridge is not expected to be empty");
} else if (strcmp(propBuf, "0") != 0) {
snprintf(nativeBridgeLibrary, sizeof("-XX:NativeBridge=") + PROPERTY_VALUE_MAX,
"-XX:NativeBridge=%s", propBuf);
addOption(nativeBridgeLibrary);
}
}
initArgs.version = JNI_VERSION_1_4;
initArgs.options = mOptions.editArray();
initArgs.nOptions = mOptions.size();
initArgs.ignoreUnrecognized = JNI_FALSE;
/*
* Initialize the VM.创建java虚拟机对象。
* 执行成功后,虚拟机便准备就绪,这时候java世界就可以分发JNI调用了。
* 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");
goto bail;
}
result = 0;
bail:
return result;
}
根据代码可以看出startVM主要做了两部分工作:一是通过属性系统获取大量虚拟机配置信息,以此设置虚拟机参数;二是调用JNI_CreateJavaVM函数创建虚拟机实例。
虚拟机参数很多,可以通过adb命令查看:adb shell dalvikvm。
JNI_CreateJavaVM不再向下跟踪,可以参考:点击打开链接
2、注册JNI方法
上面我们分析了是如何创建Dalvik虚拟机的,下面我们接着分析start方法的第二步重要工作:注册Android核心类的JNI函数。这些函数是java世界调用native方法的基础,是连接java世界和C/C++世界的桥梁。
/*
* Register android native functions with the VM.
*/
/*static*/ 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.)
*/
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.
*/
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;
}
在startReg函数中首先调用了androidSetCerateThreadFunc函数,这个函数用来设置一个线程创建钩子javaCreateThreadEtc。这个线程创建钩子是用来干什么的呢?是用来初始化一个Native线程的JNI环境的,也就是说当我们在C++代码中创建一个Native线程的时候,会调用javaCreateThreadEtc函数来初始化该Native线程的JNI环境。
调用register_jni_procs函数来注册Android核心类的JNI方法。在注册JNI方法的过程中,需要在Native代码中引用到一些JAVA对象,这些Java对象引用需要记录在当前线程的一个Native堆栈中。但是此时Dalvik虚拟机还没有真正运行起来,也就是当前线程的Native堆栈还没有准备就绪。那么在这种情况下,Android是如何处理的呢?在注册JNI方法之前,调用JNIEnv对象的PushLocalFrame函数在当前线程的Native堆栈中压入一个帧(Frame),这个帧是一个本地帧,只是用来保存java对象在Native代码中的本地引用;并且在注册JNI方法之后,调用JNIEnv对象的PopLocalFrame函数将帧弹出堆栈。在本地函数的入口处调用PushLocalFrame,在函数返回前调用PopLocalFrame,这样在两个函数之间创建的局部引用都会有效管理和释放,也就高效管理了局部引用的生命周期。
startReg函数的关键是调用register_jni_procs函数注册JNI方法。
注意:在Android应用框架层有很多地方调用Native方法,这些方法的实现都借助于本地方法。这里便是注册Native方法的JNI实现方法,Android是采用注册方式实现Native方法和JNI方法的关联。register_jni_procs的实现如下:
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;
}
从前面的调用过程可以知道
,参数array指向的是全局变量gRegJNI所描述的一个JNI方法注册函数表,其中,每一个表项都用一个RegJNIRec对象来描述,而每一个RegJNIRec对象都有一个成员变量mProc,指向一个JNI方法注册函数。通过依次调用这些注册函数,就可以将Android核心类的JNI方法注册到前面的所创建的Dalvik虚拟机中去。
那么我们看一下RegJNIRec到底是什么呢,代码如下:
#ifdef NDEBUG
#define REG_JNI(name) { name } /* 定义REG_JNI宏,宏以name为参数*/
struct RegJNIRec { /* 定义一个结构体RegJNIRec,结构体的元素是一个函数指针,参数类型是(JNIEnv*) */
int (*mProc)(JNIEnv*);
};
#else
#define REG_JNI(name) { name, #name }
struct RegJNIRec {
int (*mProc)(JNIEnv*);
const char* mName;
};
#endif
从代码中可以看出RegJNIRec是一个结构体,结构体的元素是一个函数指针。我们看一下gRegJNI描述的JNI方法注册函数表都注册了哪些Android核心类的JNI方法,代码如下:
static const RegJNIRec gRegJNI[] = {
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_content_AssetManager),
REG_JNI(register_android_content_StringBlock),
REG_JNI(register_android_content_XmlBlock),
REG_JNI(register_android_emoji_EmojiFactory),
REG_JNI(register_android_text_AndroidCharacter),
REG_JNI(register_android_text_StaticLayout),
REG_JNI(register_android_text_AndroidBidi),
REG_JNI(register_android_view_InputDevice),
REG_JNI(register_android_view_KeyCharacterMap),
REG_JNI(register_android_os_Process),
REG_JNI(register_android_os_SystemProperties),
REG_JNI(register_android_os_Binder),
REG_JNI(register_android_os_Parcel),
REG_JNI(register_android_nio_utils),
REG_JNI(register_android_graphics_Graphics),
REG_JNI(register_android_view_DisplayEventReceiver),
REG_JNI(register_android_view_RenderNode),
REG_JNI(register_android_view_RenderNodeAnimator),
REG_JNI(register_android_view_GraphicBuffer),
REG_JNI(register_android_view_GLES20Canvas),
REG_JNI(register_android_view_HardwareLayer),
REG_JNI(register_android_view_ThreadedRenderer),
REG_JNI(register_android_view_Surface),
REG_JNI(register_android_view_SurfaceControl),
REG_JNI(register_android_view_SurfaceSession),
REG_JNI(register_android_view_TextureView),
REG_JNI(register_com_android_internal_view_animation_NativeInterpolatorFactoryHelper),
REG_JNI(register_com_google_android_gles_jni_EGLImpl),
REG_JNI(register_com_google_android_gles_jni_GLImpl),
REG_JNI(register_android_opengl_jni_EGL14),
REG_JNI(register_android_opengl_jni_EGLExt),
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_opengl_jni_GLES30),
REG_JNI(register_android_opengl_jni_GLES31),
REG_JNI(register_android_opengl_jni_GLES31Ext),
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_CreateJavaOutputStreamAdaptor),
REG_JNI(register_android_graphics_Canvas),
REG_JNI(register_android_graphics_CanvasProperty),
REG_JNI(register_android_graphics_ColorFilter),
REG_JNI(register_android_graphics_DrawFilter),
REG_JNI(register_android_graphics_FontFamily),
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_SurfaceTexture),
REG_JNI(register_android_graphics_Typeface),
REG_JNI(register_android_graphics_Xfermode),
REG_JNI(register_android_graphics_YuvImage),
REG_JNI(register_android_graphics_pdf_PdfDocument),
REG_JNI(register_android_graphics_pdf_PdfEditor),
REG_JNI(register_android_graphics_pdf_PdfRenderer),
REG_JNI(register_android_database_CursorWindow),
REG_JNI(register_android_database_SQLiteConnection),
REG_JNI(register_android_database_SQLiteGlobal),
REG_JNI(register_android_database_SQLiteDebug),
REG_JNI(register_android_os_Debug),
REG_JNI(register_android_os_FileObserver),
REG_JNI(register_android_os_MessageQueue),
REG_JNI(register_android_os_SELinux),
REG_JNI(register_android_os_Trace),
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_os_MemoryFile),
REG_JNI(register_com_android_internal_os_ZygoteInit),
REG_JNI(register_com_android_internal_os_Zygote),
REG_JNI(register_com_android_internal_util_VirtualRefBasePtr),
REG_JNI(register_android_hardware_Camera),
REG_JNI(register_android_hardware_camera2_CameraMetadata),
REG_JNI(register_android_hardware_camera2_legacy_LegacyCameraDevice),
REG_JNI(register_android_hardware_camera2_legacy_PerfMeasurement),
REG_JNI(register_android_hardware_camera2_DngCreator),
REG_JNI(register_android_hardware_SensorManager),
REG_JNI(register_android_hardware_SerialPort),
REG_JNI(register_android_hardware_SoundTrigger),
REG_JNI(register_android_hardware_UsbDevice),
REG_JNI(register_android_hardware_UsbDeviceConnection),
REG_JNI(register_android_hardware_UsbRequest),
REG_JNI(register_android_hardware_location_ActivityRecognitionHardware),
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_RemoteDisplay),
REG_JNI(register_android_media_ToneGenerator),
REG_JNI(register_android_opengl_classes),
REG_JNI(register_android_server_NetworkManagementSocketTagger),
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_app_backup_FullBackup),
REG_JNI(register_android_app_ActivityThread),
REG_JNI(register_android_app_NativeActivity),
REG_JNI(register_android_view_InputChannel),
REG_JNI(register_android_view_InputEventReceiver),
REG_JNI(register_android_view_InputEventSender),
REG_JNI(register_android_view_InputQueue),
REG_JNI(register_android_view_KeyEvent),
REG_JNI(register_android_view_MotionEvent),
REG_JNI(register_android_view_PointerIcon),
REG_JNI(register_android_view_VelocityTracker),
REG_JNI(register_android_content_res_ObbScanner),
REG_JNI(register_android_content_res_Configuration),
REG_JNI(register_android_animation_PropertyValuesHolder),
REG_JNI(register_com_android_internal_content_NativeLibraryHelper),
REG_JNI(register_com_android_internal_net_NetworkStatsFactory),
};
这里使用了宏REG_JNI,将函数名传递给结构体RegJNIRec的mProc函数指针。这些函数最终调用了jniRegisterNativeMethods方法注册JNI方法。
至此,JNI方法注册就分析到这里。
3、开启java世界
在AndroidRuntime的start方法中是通过CallStaticVoidMethod这个JNI函数调用ZygoteInit文件的main函数来开启java世界的。ZygoteInit文件位于frameworks/base/core/java/com/android/internal/os/ZygoteInit.java,定位到main方法,代码如下:
public static void main(String argv[]) {
try {
// Start profiling the zygote initialization.
SamplingProfilerIntegration.start();
boolean startSystemServer = false;
String socketName = "zygote";
String abiList = null;
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = true;
} else if (argv[i].startsWith(ABI_LIST_ARG)) {
abiList = argv[i].substring(ABI_LIST_ARG.length());
} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
socketName = argv[i].substring(SOCKET_NAME_ARG.length());
} else {
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
}
if (abiList == null) {
throw new RuntimeException("No ABI list supplied.");
}
registerZygoteSocket(socketName);/* 注册zygote服务所需的Socket,用来接收请求 */
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
preload();/* 加载class资源和resource资源 */
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();/* 强制gc */
// Disable tracing so that forked processes do not inherit stale tracing tags from
// Zygote.
Trace.setTracingEnabled(false);
if (startSystemServer) {
startSystemServer(abiList, socketName);/* 启动system_server */
}
Log.i(TAG, "Accepting command socket connections");
runSelectLoop(abiList);
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();/* zygote异常退出 */
throw ex;
}
}
ZygoteInit的main方法主要做了5部分工作:
三、Zygote开启java世界
1、注册Zygote的Socket
注册zygote服务所需要的Socket,是通过registerZygoteSocket函数来实现的,该函数绑定了zygote中的Socket,用于接收ActivityManagerService中启动应用程序的请求。
/**
* Registers a server socket for zygote command connections
*
* @throws RuntimeException when open fails
*/
private static void registerZygoteSocket(String socketName) {
if (sServerSocket == null) {
int fileDesc;
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
try {
String env = System.getenv(fullSocketName);
fileDesc = Integer.parseInt(env);
} catch (RuntimeException ex) {
throw new RuntimeException(fullSocketName + " unset or invalid", ex);
}
try {
sServerSocket = new LocalServerSocket(
createFileDescriptor(fileDesc));
} catch (IOException ex) {
throw new RuntimeException(
"Error binding to local socket '" + fileDesc + "'", ex);
}
}
}
这里的socketName是在main函数中定义的“zygote”,因此fullSocketName为“ANDROID_SOCKET_zygote”,通过调用System.getenv(fullSocketName)函数,返回在系统环境变量值定义的变量的字符串值;最后根据对应的文件描述符生成一个LocalServerSocket对象,即zygote服务端的Socket,最终该Socket将与ActivityManagerService通信,是java世界启动新进程的通道。
2、预加载Class资源和Resource资源
在ZygoteInit的main方法中创建完Socket后,便进行预加载资源,这部分功能是通过preload函数完成的,在preload函数中封装了对preloadClasses()和preloadResource()等函数的调用。
static void preload() {
Log.d(TAG, "begin preload");
preloadClasses();
preloadResources();
preloadOpenGL();
preloadSharedLibraries();
// Ask the WebViewFactory to do any initialization that must run in the zygote process,
// for memory sharing purposes.
WebViewFactory.prepareWebViewInZygote();
Log.d(TAG, "end preload");
}
2.1、preloadClasses()
该函数用于加载preloaded-classes文件中指定的java类,代码如下:
/**
* Performs Zygote process initialization. Loads and initializes
* commonly used classes.
*
* Most classes only cause a few hundred bytes to be allocated, but
* a few will allocate a dozen Kbytes (in one case, 500+K).
*/
private static void preloadClasses() {
final VMRuntime runtime = VMRuntime.getRuntime();
InputStream is;
try {
is = new FileInputStream(PRELOADED_CLASSES);
} catch (FileNotFoundException e) {
Log.e(TAG, "Couldn't find " + PRELOADED_CLASSES + ".");
return;
}
Log.i(TAG, "Preloading classes...");
long startTime = SystemClock.uptimeMillis();
// Drop root perms while running static initializers.为了安全考虑,加载前降低权限
setEffectiveGroup(UNPRIVILEGED_GID);
setEffectiveUser(UNPRIVILEGED_UID);
// Alter the target heap utilization. With explicit GCs this
// is not likely to have any effect.使用VMRuntime的setTargetHeapUtilization函数可以增强程序堆内存的处理效率。
float defaultUtilization = runtime.getTargetHeapUtilization();
runtime.setTargetHeapUtilization(0.8f);
// Start with a clean slate.
System.gc();
runtime.runFinalizationSync();
Debug.startAllocCounting();//统计两点间的内存分配情况,使用Debug.startAllocCounting()、Debug.stopAllocCounting()
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 (false) {
Log.v(TAG, "Preloading " + line + "...");
}
Class.forName(line);/*反射机制加载类*/
if (Debug.getGlobalAllocSize() > PRELOAD_GC_THRESHOLD) {
if (false) {
Log.v(TAG,
" GC at " + Debug.getGlobalAllocSize());
}
System.gc();
runtime.runFinalizationSync();
Debug.resetGlobalAllocSize();
}
count++;
} catch (ClassNotFoundException e) {
Log.w(TAG, "Class not found for preloading: " + line);
} catch (UnsatisfiedLinkError e) {
Log.w(TAG, "Problem preloading " + line + ": " + e);
} 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 {
IoUtils.closeQuietly(is);
// Restore default.
runtime.setTargetHeapUtilization(defaultUtilization);
// Fill in dex caches with classes, fields, and methods brought in by preloading.
runtime.preloadDexCaches();
Debug.stopAllocCounting();
// Bring back root. We'll need it later.还原权限
setEffectiveUser(ROOT_UID);
setEffectiveGroup(ROOT_GID);
}
}
其中,PRELOADED_CLASSES是被定义的全局变量“/system/etc/preloaded-classes”,这是一个文件,用来存放预加载的类;根据该文件的内容,我们可以得知函数中读取出来的line便是一个类,通过反射机制加载读取出来的类。preloaded-classes文件中有2000行以上,读取每一行并加载每一行指定的类需要花费较长的时间,这也是影响系统启动速度慢的原因。不过这些类预先加载到内存中,当新的应用程序启动时,可以共享这部分资源,这样便加快了应用程序启动和运行速度。
2.2、preloadResources()
preloadResources函数用于加载框架层定义的资源,代码如下:
/**
* Load in commonly used resources, so they can be shared across
* processes.
*
* These tend to be a few Kbytes, but are frequently in the 20-40K
* range, and occasionally even larger.
*/
private static void preloadResources() {
final VMRuntime runtime = VMRuntime.getRuntime();
Debug.startAllocCounting();
try {
System.gc();
runtime.runFinalizationSync();
mResources = Resources.getSystem();/*初始化全局变量mResources*/
mResources.startPreloading();/*设置初始状态,防止重复加载资源*/
if (PRELOAD_RESOURCES) {/*PRELOAD_RESOURCES设置在zygote初始化时是否加载Resource,初始值为true*/
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);
ar.recycle();
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);
ar.recycle();
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();
}
}
preloadResources共加载了两种资源:drawables和color。这些资源定义在frameworks/base/core/res/res/values/array.xml文件中,最终会被编译进frameworks-res.apk中。
3、启动system_server进程
ZygoteInit的main函数中加载完共享资源后,便开始启动system_server进程,该进程是理解框架层的基础。Android中所有的系统服务都是由该进程启动的,它的异常退出会直接导致zygote“自杀”,这样整个java世界便会崩溃。system_server进程的启动入口是startSystemServer,代码如下:
/**
* Prepare the arguments and fork for the system server process.
*/
private static boolean startSystemServer(String abiList, String socketName)
throws MethodAndArgsCaller, RuntimeException {
long capabilities = posixCapabilitiesAsBits(
OsConstants.CAP_BLOCK_SUSPEND,
OsConstants.CAP_KILL,
OsConstants.CAP_NET_ADMIN,
OsConstants.CAP_NET_BIND_SERVICE,
OsConstants.CAP_NET_BROADCAST,
OsConstants.CAP_NET_RAW,
OsConstants.CAP_SYS_MODULE,
OsConstants.CAP_SYS_NICE,
OsConstants.CAP_SYS_RESOURCE,
OsConstants.CAP_SYS_TIME,
OsConstants.CAP_SYS_TTY_CONFIG
);
/* Hardcoded command line to start the system server启动system_server的命令行参数 */
String args[] = {
"--setuid=1000",/*设置用户ID为1000,即SYSTEM_UID,系统进程*/
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1032,3001,3002,3003,3006,3007",
"--capabilities=" + capabilities + "," + capabilities,
"--runtime-init",
"--nice-name=system_server",/*设置进程名*/
"com.android.server.SystemServer",/*设置要启动的类名*/
};
ZygoteConnection.Arguments parsedArgs = null;
int pid;
try {
parsedArgs = new ZygoteConnection.Arguments(args);/*将args数组分解成Arguments类型的对象*/
ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
/* Request to fork the system server process.调用系统函数fork()创建子进程system_server */
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.debugFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
/* For child process */
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
handleSystemServerProcess(parsedArgs);/*在子进程中调用handleSystemServerProcess*/
}
return true;/*在父进程中返回*/
}
到这里zygote做了第一次分裂,fork出系统服务的总管system_server进程。这个过程分为以下两个重要的步骤:通过forkSystemServer创建system_server子进程;在子进程中调用handleSystemServerProcess方法。
3.1、调用forkSystemServer创建system_server子进程。
创建system_server的第一步便是调用Zygote类的forkSystemServer方法,该方法位于frameworks/base/core/java/com/android/internal/os/Zygote.java类中,在forkSystemServer方法中通过调用Native方法nativeForkSystemServer来完成启动system_server进程的任务。代码如下:
/**
* Special method to start the system server process. In addition to the
* common actions performed in forkAndSpecialize, the pid of the child
* process is recorded such that the death of the child process will cause
* zygote to exit.
*
* @param uid the UNIX uid that the new process should setuid() to after
* fork()ing and and before spawning any threads.
* @param gid the UNIX gid that the new process should setgid() to after
* fork()ing and and before spawning any threads.
* @param gids null-ok; a list of UNIX gids that the new process should
* setgroups() to after fork and before spawning any threads.
* @param debugFlags bit flags that enable debugging features.
* @param rlimits null-ok an array of rlimit tuples, with the second
* dimension having a length of 3 and representing
* (resource, rlim_cur, rlim_max). These are set via the posix
* setrlimit(2) call.
* @param permittedCapabilities argument for setcap()
* @param effectiveCapabilities argument for setcap()
*
* @return 0 if this is the child, pid of the child
* if this is the parent, or -1 on error.
*/
public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags,
int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
VM_HOOKS.preFork();
int pid = nativeForkSystemServer(
uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities);
VM_HOOKS.postForkCommon();
return pid;
}
native private static int nativeForkSystemServer(int uid, int gid, int[] gids, int debugFlags,
int[][] rlimits, long permittedCapabilities, long effectiveCapabilities);
nativeForkSystemServer的JNI层代码实现位于/dalvik/vm/native/dalvik_system_Zygote.cpp中,函数名为Dalvik_dalvik_system_Zygote_forkSystemServer,代码如下:
static void Dalvik_dalvik_system_Zygote_forkSystemServer(
const u4* args, JValue* pResult)
{
pid_t pid;
pid = forkAndSpecializeCommon(args, true); //启动system_server进程
/* The zygote process checks whether the child process has died or not. */
if (pid > 0) {//pid大于0,说明是在父进程中
int status;
ALOGI("System server process %d has been created", pid);
gDvm.systemServerPid = pid; //在虚拟机中记录system_server进程的ID
/* There is a slight window that the system server process has crashed
* but it went unnoticed because we haven't published its pid yet. So
* we recheck here just to make sure that all is well.
*/
if (waitpid(pid, &status, WNOHANG) == pid) {//堵塞,等待system_server进程
ALOGE("System server process %d has died. Restarting Zygote!", pid);
kill(getpid(), SIGKILL);//一旦上面的等待返回,说明进程pid(system_server)已终止,此时Zygote杀死自己
}
}
RETURN_INT(pid);
}
该函数的功能主要分为两部分:一是启动system_server进程;二是监控system_server进程的启动结果。system_server进程的启动是由forkAndSpecializeCommon完成的,在forkAndSpecializeCommon函数中调用系统函数fork创建子进程,并且在创建前设置信号处理函数setSignalHandler(),在setSignalHandler方法中调用系统函数sigaction处理SIGCHLD信号(子进程退出信号),指定处理函数sigchldHandler,如果system_server出现异常,就会自杀。
3.2、在子进程中调用handleSystemServerProcess方法
system_server进程启动之后,便开始执行handleSystemServerProcess方法,代码如下:
/**
* Finish remaining work for the newly forked system server process.
*/
private static void handleSystemServerProcess(
ZygoteConnection.Arguments parsedArgs)
throws ZygoteInit.MethodAndArgsCaller {
closeServerSocket();//关闭fork时从zygote继承下来的socket
// set umask to 0077 so new files and directories will default to owner-only permissions.
Os.umask(S_IRWXG | S_IRWXO);//设置文件的默认权限
if (parsedArgs.niceName != null) {
Process.setArgV0(parsedArgs.niceName);//system_server
}
final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
if (systemServerClasspath != null) {
performSystemServerDexOpt(systemServerClasspath);
}
if (parsedArgs.invokeWith != null) {
String[] args = parsedArgs.remainingArgs;
// If we have a non-null system server class path, we'll have to duplicate the
// existing arguments and append the classpath to it. ART will handle the classpath
// correctly when we exec a new process.
if (systemServerClasspath != null) {
String[] amendedArgs = new String[args.length + 2];
amendedArgs[0] = "-cp";
amendedArgs[1] = systemServerClasspath;
System.arraycopy(parsedArgs.remainingArgs, 0, amendedArgs, 2, parsedArgs.remainingArgs.length);
}
WrapperInit.execApplication(parsedArgs.invokeWith,
parsedArgs.niceName, parsedArgs.targetSdkVersion,
null, args);
} else {
ClassLoader cl = null;
if (systemServerClasspath != null) {
cl = new PathClassLoader(systemServerClasspath, ClassLoader.getSystemClassLoader());
Thread.currentThread().setContextClassLoader(cl);
}
/*
* Pass the remaining arguments to SystemServer.
*/
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
}
/* should never reach here */
}
在handleSystemServerProcess方法中做了一些清理和初始化工作,接着调用RuntimeInit.zygoteInit方法。
/**
* The main function called when started through the zygote process. This
* could be unified with main(), if the native code in nativeFinishInit()
* were rationalized with Zygote startup.
*
* Current recognized args:
*
* -
[--]
*
*
* @param targetSdkVersion target SDK version
* @param argv arg strings
*/
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
redirectLogStreams();
commonInit();
nativeZygoteInit();
applicationInit(targetSdkVersion, argv, classLoader);
}
在zygoteInit方法中封装了四个方法的调用,对应四个步骤实现不同的初始化操作,分别介绍如下:
1)、redirectLogStreams方法重定向标准I/O操作,重定向到Android标准的日志系统。
/**
* Redirect System.out and System.err to the Android log.
*/
public static void redirectLogStreams() {
System.out.close();
System.setOut(new AndroidPrintStream(Log.INFO, "System.out"));
System.err.close();
System.setErr(new AndroidPrintStream(Log.WARN, "System.err"));
}
2)、commonInit方法初始化一些通用设置
private static final void commonInit() {
if (DEBUG) Slog.d(TAG, "Entered RuntimeInit!");
/* set default handler; this applies to all threads in the VM */
Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler());//设置未捕获异常的默认处理函数
/*
* Install a TimezoneGetter subclass for ZoneInfo.db
*/
TimezoneGetter.setInstance(new TimezoneGetter() {
@Override
public String getId() {
return SystemProperties.get("persist.sys.timezone");
}
});
TimeZone.setDefault(null);
/*
* Sets handler for java.util.logging to use Android log facilities.
* The odd "new instance-and-then-throw-away" is a mirror of how
* the "java.util.logging.config.class" system property works. We
* can't use the system property here since the logger has almost
* certainly already been initialized.
*/
LogManager.getLogManager().reset();//Android log配置
new AndroidConfig();
/*
* Sets the default HTTP User-Agent used by HttpURLConnection.
*/
String userAgent = getDefaultUserAgent();
System.setProperty("http.agent", userAgent);
/*
* Wire socket tagging to traffic stats.
*/
NetworkManagementSocketTagger.install();
/*
* If we're running in an emulator launched with "-trace", put the
* VM into emulator trace profiling mode so that the user can hit
* F9/F10 at any time to capture traces. This has performance
* consequences, so it's not something you want to do always.
*/
String trace = SystemProperties.get("ro.kernel.android.tracing");
if (trace.equals("1")) {
Slog.i(TAG, "NOTE: emulator trace profiling enabled");
Debug.enableEmulatorTraceOutput();
}
initialized = true;
}
3)、nativeZygoteInit方法开启Binder通信
nativeZygoteInit是一个native方法,其JNI实现方法位于AndroidRuntime.cpp中,方法名为com_android_internal_os_RuntimeInit_nativiZygoteInit,代码如下:
static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
gCurRuntime->onZygoteInit();
}
这里调用onZygoteInit方法,这里onZygoteInit是一个虚函数,直接调用子类AppRuntime.onZygoteInit,代码位于frameworks/base/cmd/app_process/App_main.cpp中。
virtual void onZygoteInit()
{
// Re-enable tracing now that we're no longer in Zygote.
atrace_set_tracing_enabled(true);
sp proc = ProcessState::self();
ALOGV("App process: starting thread pool.\n");
proc->startThreadPool();//创建PoolThread对象,用于Binder通信
}
4)、invokeStaticMain方法抛出异常
applicationInit方法做了虚拟机设置,并转化了参数后,直接调用invokeStaticMain方法,这里直接分析invokeStaticMain,代码如下:
/**
* Invokes a static "main(argv[]) method on class "className".
* Converts various failing exceptions into RuntimeExceptions, with
* the assumption that they will then cause the VM instance to exit.
*
* @param className Fully-qualified class name
* @param argv Argument vector for main()
* @param classLoader the classLoader to load {@className} with
*/
private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
Class> cl;
try {
cl = Class.forName(className, true, classLoader);//利用java反射机制加载类信息,className是com.android.server.SystemServer
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Missing class when invoking static main " + className,
ex);
}
Method m;
try {
m = cl.getMethod("main", new Class[] { String[].class });//加载SystemServer类的main函数
} catch (NoSuchMethodException ex) {
throw new RuntimeException(
"Missing static main on " + className, ex);
} catch (SecurityException ex) {
throw new RuntimeException(
"Problem getting static main on " + className, ex);
}
int modifiers = m.getModifiers();//利用java的反射机制,判断main函数的修饰符是否是static和public
if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
throw new RuntimeException(
"Main method is not public and static on " + className);
}
/*
* This throw gets caught in ZygoteInit.main(), which responds
* by invoking the exception's run() method. This arrangement
* clears up all the stack frames that were required in setting
* up the process.
*/
throw new ZygoteInit.MethodAndArgsCaller(m, argv);//抛出异常
}
invokeStaticMain方法利用java的反射机制加载类的信息后,最后抛出一个MethodAndArgsCaller异常,那么在哪里进行的异常捕获呢?
4、执行MethodAndArgsCaller的run方法
在ZygoteInit的main方法中捕获了MethodAndArgsCaller异常,便执行run方法。
public static void main(String argv[]) {
try {
......
registerZygoteSocket(socketName);
......
preload();
......
if (startSystemServer) {
startSystemServer(abiList, socketName);
}
Log.i(TAG, "Accepting command socket connections");
runSelectLoop(abiList);
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}
分析下MethodAndArgsCaller类中都做了哪些事情。
/**
* Helper exception class which holds a method and arguments and
* can call them. This is used as part of a trampoline to get rid of
* the initial process setup stack frames.
*/
public static class MethodAndArgsCaller extends Exception
implements Runnable {
/** method to call */
private final Method mMethod;
/** argument array */
private final String[] mArgs;
public MethodAndArgsCaller(Method method, String[] args) {//构造方法中传入了方法和参数
mMethod = method;
mArgs = args;
}
public void run() {
try {
mMethod.invoke(null, new Object[] { mArgs });//利用java反射机制调用这个方法
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (InvocationTargetException ex) {
Throwable cause = ex.getCause();
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
} else if (cause instanceof Error) {
throw (Error) cause;
}
throw new RuntimeException(ex);
}
}
}
MethodAndArgsCaller类既是一个异常类又是一个线程,异常处理代码中直接调用了这个线程的run方法,并执行了传入的com.android.server.SystemServer类的main方法。invokeStaticMain方法抛出异常的目的是执行com.android.server.SystemServer类的main方法,通过这种方式,可以直接从调用栈中跳出,并返回到ZygoteInit的main方法中。
system_server绕了一大圈执行了SystemServer的main方法,那么SystemServer又承担了什么使命呢?首先分析一下com.android.server.SystemServer类的main方法中做了哪些事情,代码位于:\frameworks\base\services\java\com\android\server\SystemServer.java,如下:
/**
* The main entry point from zygote.
*/
public static void main(String[] args) {
new SystemServer().run();
}
private void run() {
// If a device's clock is before 1970 (before 0), a lot of
// APIs crash dealing with negative numbers, notably
// java.io.File#setLastModified, so instead we fake it and
// hope that time from cell towers or NTP fixes it shortly.
if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
Slog.w(TAG, "System clock is before 1970; setting to 1970.");
SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
}
// Here we go!
Slog.i(TAG, "Entered the Android system server!");
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, SystemClock.uptimeMillis());
// In case the runtime switched since last boot (such as when
// the old runtime was removed in an OTA), set the system
// property so that it is in sync. We can't do this in
// libnativehelper's JniInvocation::Init code where we already
// had to fallback to a different runtime because it is
// running as root and we need to be the system user to set
// the property. http://b/11463182
SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());
// Enable the sampling profiler.
if (SamplingProfilerIntegration.isEnabled()) {//判断是否开启性能统计
SamplingProfilerIntegration.start();//启动性能统计
mProfilerSnapshotTimer = new Timer();
mProfilerSnapshotTimer.schedule(new TimerTask() {
@Override
public void run() {
SamplingProfilerIntegration.writeSnapshot("system_server", null);//结束统计并生成结果文件
}
}, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);
}
// Mmmmmm... more memory!申请更多的内存
VMRuntime.getRuntime().clearGrowthLimit();
// The system server has to run all of the time, so it needs to be
// as efficient as possible with its memory usage.提高堆内存使用效率
VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
// Some devices rely on runtime fingerprint generation, so make sure
// we've defined it before booting further.
Build.ensureFingerprintProperty();
// Within the system server, it is an error to access Environment paths without
// explicitly specifying a user.
Environment.setUserRequired(true);
// Ensure binder calls into the system always run at foreground priority.
BinderInternal.disableBackgroundScheduling(true);
// Prepare the main looper thread (this thread).
android.os.Process.setThreadPriority(
android.os.Process.THREAD_PRIORITY_FOREGROUND);
android.os.Process.setCanSelfBackground(false);
Looper.prepareMainLooper();
// Initialize native services.加载libandroid_servers.so库文件
System.loadLibrary("android_servers");
nativeInit();
// Check whether we failed to shut down last time we tried.
// This call may not return.
performPendingShutdown();
// Initialize the system context.
createSystemContext();
// Create the system service manager.
mSystemServiceManager = new SystemServiceManager(mSystemContext);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
// Start services.
try {
startBootstrapServices();
startCoreServices();
startOtherServices();
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
}
// For debug builds, log event loop stalls to dropbox for analysis.
if (StrictMode.conditionallyEnableDebugLogging()) {
Slog.i(TAG, "Enabled StrictMode for system server main thread.");
}
// Loop forever.
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
nativeInit是本地方法,具体实现位于\frameworks\base\services\core\jni\com_android_server_SystemServer.cpp,只是启动Sensor Service。SensorService是C语言实现的系统服务,因此成为Native System Service。
static void android_server_SystemServer_nativeInit(JNIEnv* env, jobject clazz) {
char propBuf[PROPERTY_VALUE_MAX];
property_get("system_init.startsensorservice", propBuf, "1");
if (strcmp(propBuf, "1") == 0) {
// Start the sensor service
SensorService::instantiate();
}
}