Zygote启动分析
来源:互联网 发布:古代画家排名知乎 编辑:程序博客网 时间:2024/04/27 15:12
基于性能的考虑,Dalvik虚拟机只启动一次,新的实例将从第一次启动的Dalvik中拷贝。这个功能是通过系统服务Zygote来实现的。
Zygote的启动过程简述如下:首先,它预初始化和预加载通用的Android类到它的堆中。然后,它监听在Socket端口上,等待启动一个新的Android应用程序的命令。当接收到一个启动应用程序命令,它将利用已经加载的应用程序fork出一个新的进程。该进程就是被启动的应用程序,且与原始的Zygote进程共享同一个写时复制(copy-on-write)映射的堆。因此,Zygote的堆被链接到该新进程。如果该应用程序只从堆中读取数据,那么就一直与Zygote共享堆。但是,一旦应用程序在堆上执行写操作,那么堆对应的内存页被会被复制且会链接到新页上。这样,应用程序就可以修改过堆中的数据而不用担心会影响Zygote进程的堆了。
当一个新的Android应用程序产生时,它使用Zygote的内存布局,因此,对每个应用程序来说,它们的内存布局是一样的。
下面分析一下代码的流程:
1. 根据init.rc的启动服务的命令,将运行/system/bin/app_process启动zygote。 app_process的命令参数形式为:app_process[java-options] cmd-dir start-class-name [options],
由此可知,传入虚拟机的参数为-Xzygote,首先,-X一般是虚拟机的非标准选项,允许虚拟机定义一些特别的选项,其中zygote就是dalvik虚拟机定义的特制的选项,表示当前运行在zygote模式。在zygote模式下,虚拟机不会启动额外的线程。命令所在的目录是/system/bin,传给app_process的参数是--zygote和--start-system-server。这两个参数表示当前启动的进程名字叫zygote,并且要启动SystemServer。
while (i < argc) {
const char* arg = argv[i++];
if (!parentDir) {
parentDir = arg;
} else if (strcmp(arg, "--zygote") == 0) {
zygote = true;
niceName = "zygote";
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true;
} else if (strcmp(arg, "--application") == 0) {
application = true;
} else if (strncmp(arg, "--nice-name=", 12) == 0) {
niceName = arg + 12;
} else {
className = arg;
break;
}
}
2. 接下来,将启动ZygoteInit这个类。在启动这个类之前,会调用startVM(JavaVM** pJavaVM, JNIEnv** pEnv)创建一个dalvik虚拟机,其中JavaVM代表dalvik虚拟机的一个实例,每个进程只有一个实例,JNIEnv代表一个dalvik虚拟机运行环境,每个线程拥有一个实例。接下来通过调用startReg(env)来向虚拟机注册一些JNI本地函数。最后进入ZygoteInit类中的入口函数main中去运行。
…
if (zygote) {
runtime.start("com.android.internal.os.ZygoteInit",
startSystemServer ? "start-system-server" : "");
} else if (className) {
…
在Android::start()方法中,启动虚拟机以及注册Android的JNI本地函数。
void AndroidRuntime::start(const char* className, const char* options)
{
...
/* start the virtual machine */
JNIEnv* env;
if (startVm(&mJavaVM, &env) != 0) {
return;
}
onVmCreated(env);
/*
* Register android functions.
*/
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
...
/*
* Start VM. This thread becomes the main thread of the VM, and will
* not return until the VM exits.
*/
char* slashClassName = toSlashClassName(className);
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
if (startMeth == NULL) {
ALOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
env->CallStaticVoidMethod(startClass, startMeth, strArray);
#if 0
if (env->ExceptionCheck())
threadExitUncaughtException(env);
#endif
}
}
...
}
3. 接下来,将进入ZygoteInit的main方法,首先registerZygoteSocket()会注册一个服务器端的本地Socket,Socket的路径由环境变量ANDROID_SOCKET_zygote指定。它的主要目的是监听启动应用程序的命令请求,并fork一个子进程来处理启动相应的应用程序。然后,preload()函数会预加载一些资源和一些通用类(由preloaded-classes资源文件指定)。接下来,调用startSystemServer()来启动SystemServer进程。主线程继续执行代码,最后阻塞在runSelectLoop(),在该函数中将接受请求,并fork子进程来处理。
public static void main(String argv[]) {
try {
...
registerZygoteSocket();
...
preload();
...
if (argv[1].equals("start-system-server")) {
startSystemServer();
} else if (!argv[1].equals("")) {
throw new RuntimeException(argv[0] + USAGE_STRING);
}
Log.i(TAG, "Accepting command socket connections");
runSelectLoop();
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}
4. 最后我们看一下,如何启动SystemServer。
在startSystemServer()中,进入handleSystemServerProcess(…)。最终调用的是RuntimeInit.zygoteInit(…),这个函数会执行一些通用的初始化,最后通过applicationInit(…)调用com.android.server.SystemServer的main函数。
5. SystemServer会开启一个ServerThread线程,在该线程中启动一系列服务后,最后会通过ActivityManagerService.self().systemReady(…) -> resumeTopActivityLocked->startHomeActivityLocked启动Home Activity,即Launcher。
- zygote启动分析
- Zygote启动分析
- zygote启动过程分析
- Zygote,SystemServer启动分析
- zygote,systemserver 启动分析
- Zygote 启动流程分析
- android启动过程分析--启动zygote
- android启动过程分析--启动zygote
- Zygote进程启动过程的源代码分析
- Zygote进程启动过程源代码分析
- 图解Android - Zygote, System Server 启动分析
- 图解Android - Zygote, System Server 启动分析
- 图解Android - Zygote, System Server 启动分析
- 图解Android - Zygote, System Server 启动分析 .
- android zygote之启动过程分析
- 图解Android - Zygote, System Server 启动分析
- 图解Android - Zygote, System Server 启动分析
- Android5 Zygote 与 SystemServer 启动流程分析
- java 初级
- 如何设置编码器分片参数
- PROPHET路由算法基本思想
- 我搜集的关于DDS的全部资料包括OpenDDS的源码
- 写注册表实现开机启动
- Zygote启动分析
- H.264难点问题分析
- UC2POCKET 解决从UC到pocket的分享问题
- css3 display:box
- 开始写自己的博客
- 实现运行时自动隐藏
- ACM2 递归 n分成k份
- org.apache.commons.dbcp.SQLNestedException: Cannot get a connection, pool ex
- cocos2dx使用TiledMap创建斜45度地图场景