Zygote 启动:
1, init.rc 启动 zygote :
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
socket zygote stream 666
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
2, app_process 即: framework/base/cmds/app_process/App_main.cpp : ----- main 中 AndroidRuntime的 start 调用
set_process_name("zygote");
runtime.start("com.android.internal.os.ZygoteInit",
startSystemServer);
由于:
class AppRuntime : public AndroidRuntime
继承关系,调用的是 AndroidRuntime的start 函数:
void AndroidRuntime::start(const char* className, const bool startSystemServer)
{
// 设置 ANDROID_ROOT 为/system
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.");
goto bail;
}
setenv("ANDROID_ROOT", rootDir, 1);
}
// 启动虚拟机
/* start the virtual machine */
if (startVm(&mJavaVM, &env) != 0)
goto bail;
}
------------- 调用 startVm () :
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv)
{
//唉,大部分都是设置java虚拟机的启动参数。不过有几个参数比较重要。
//checkjni,可能没使用过jni的一辈子都不能体会
//说白了,就是我们在C++层调用jni函数的时候,会对参数或者什么的进行检查
//要是不合法的话,直接把虚拟机exit!第一个影响速度,第二个是影响程序。
//这个只作为开发时候使用。
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;
}
}
//设置虚拟机最大heapsize,才给16M,似乎有点少,尤其是在做图片操作的
//随便一个几百兆的图片就会把虚拟机搞死。
strcpy(heapsizeOptsBuf, "-Xmx");
property_get("dalvik.vm.heapsize", heapsizeOptsBuf+4, "16m");
opt.optionString = heapsizeOptsBuf;
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);
}
//具体dalvik虚拟机有哪些参数,可以参考Dalvik的说明
//反正调用了下面这个函数,虚拟机就按您指定的参数启动了。
if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
LOGE("JNI_CreateJavaVM failed\n");
goto bail;
}
result = 0;
bail:
free(stackTraceFile);
return result;
}
3, 在 启动虚拟机后,调用 startReg() 注册Android 函数:
/*
* 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);
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);
if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
env->PopLocalFrame(NULL);
return -1;
}
env->PopLocalFrame(NULL);
//createJavaThread("fubar", quickTest, (void*) "hello");
return 0;
}
上述register_jni_procs()就是注册 : gRegJNI全局变量的函数: frameworks/base/core/jni/AndroidRuntime.cpp
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),
....
}
上述注册的函数,提供JAVA调用native函数。
4, 在调用完上述的StartReg函数后,即将进入到JAVA世界:
if (startReg(env) < 0) {
goto bail;
}
jclass stringClass;
jobjectArray strArray;
jstring classNameStr;
jstring startSystemServerStr;
//下面这些话,都是把c++的字符串转成JAVA的字符串
//
stringClass = env->FindClass("java/lang/String");
//构造一个String数组,元素个数为2
strArray = env->NewObjectArray(2, stringClass, NULL);
classNameStr = env->NewStringUTF(className);
env->SetObjectArrayElement(strArray, 0, classNameStr);
startSystemServerStr = env->NewStringUTF(startSystemServer ? "true" : "false");
env->SetObjectArrayElement(strArray, 1, startSystemServerStr);
//java应用程序不也有main函数吗?上面的就是把C++传进来的参数,变成java的参数
[
“com.android.internal.os.ZygoteInit”,
“true”
]
jclass startClass;
jmethodID startMeth;
//
startClass = env->FindClass(slashClassName);
// 下面这个JNI调用,就真正进入java层了
startMeth = env->GetStaticMethodID(startClass, "main","([Ljava/lang/String;)V");
//下面调用的就是com.android.internal.os.ZygoteInit类的main函数
//最后一个参数是true
env->CallStaticVoidMethod(startClass, startMeth, strArray);
bail:
free(slashClassName);
}
进入到: frameworks/base/core/java/com/android/internal/os/ZygoteInit.java 中的main() 函数
跑完AndroidRuntime.cpp的start(...) 函数后,跳到ZygoteInit.java的main()函数
public static void main(String argv[]) {
try {
VMRuntime.getRuntime().setMinimumHeapSize(5 * 1024 * 1024);
// Start profiling the zygote initialization.
SamplingProfilerIntegration.start();
//注册 zygote的端口
registerZygoteSocket();
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
//预加载一些类。
preloadClasses();
//cacheRegisterMaps();
//预加载一些资源文件
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");
if (ZYGOTE_FORK_MODE) { // ZYGOTE_FORK_MODE = false
runForkMode();
} else {
runSelectLoopMode(); //监听socket
}
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}
主要完成以下的4个工作:
1) 建立 IPC 通信服务器 ----- registerZygoteSocket
2) 预加载类和资源: ------ preloadClasses() / preloadResources()
3) 启动 system_server --------- startSystemServer();
4) 等待 Zygote 被调用 ---------- runSelectLoopMode();
5, Zygote 孵化器:
由上述可知: Zygote是一个简单的典型C/S结构,Zygote为提供服务一端,其他进程作为一个客户向服务端申请 “孵化”请求; Zygote接受到消息后产生一个新的进程。
在 等待 Zygote 被调用: runSelectLoopMode()
------ Accept socket connection
----------- Conntecion.RunOnce()
------------- Read argument
------ folkAndSpecialize
Zygote.java:
native public static int forkAndSpecialize(int uid, int gid, int[] gids,
int debugFlags, int[][] rlimits);
folkAndSpecialize调用的native函数为:dalvik/vm/native/dalvik_system_Zygote.c
{ "forkAndSpecialize", "(II[II[[I)I",
Dalvik_dalvik_system_Zygote_forkAndSpecialize },
可以看到Activity 利用 Zygote复制 新进程的方式:
可以看到子进程继承了父进程的资源。