2.1 init.rc启动脚本
Android系统在启动时,第一个启动的进程就是init进程,也就是我们说的一号进程,我们通过下图的ps命令可以看到init进程号为1。接着,init进程根据读取/init.rc文件中的配置创建并启动app_process进程,也就是我们的Zygote进程,其启动参数见下表所示。
init.rc文件:
… service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server class main socket zygote stream 660 root system onrestart write /sys/android_power/request_state wake onrestart write /sys/power/state on onrestart restart media onrestart restart netd …
上面的文件参数:
service表示Zygote进程是以服务的形式启动;
/system/bin/app_process表示它对应的文件位置;
后面四个选项就是Zygote进程的启动参数,其中—start-system-server表示Zygote进程启动完以后,需要马上运行SystemServer进程。
下面通过ps命令获取当前运行的进程信息
接着我们查看android源码/framework/base/cmds/app_process源码的入口函数main:
int main(int argc, char* const argv[]) { … AppRuntime runtime; … bool zygote = false; bool startSystemServer = false; bool application = false; const char* parentDir = NULL; const char* niceName = NULL; const char* className = NULL; 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; } } … if (zygote) { //Zygote模式启动(创建Zygote进程和SystemServer进程) runtime.start("com.android.internal.os.ZygoteInit", startSystemServer ? "start-system-server" : ""); } else if (className) { //非Zygote模式启动(创建应用程序的进程) // Remainder of args get passed to startup class main() runtime.mClassName = className; runtime.mArgC = argc - i; runtime.mArgV = argv + i; runtime.start("com.android.internal.os.RuntimeInit", application ? "application" : "tool"); } 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; } }
通过init.rc中Zygote的启动参数,我们知道arg参数中包含了” --zygote”和”--zygote --start-system-server”参数。所以,zygote和startSystemServer变量都为true。这表示Zygote进程启动完以后,会接着启动SystemServer进程。
从上面的代码,我们知道Zygote分两种模式启动,分别是Zygote模式和非Zygote模式。当处于Zygote模式时,系统会调用com.android.internal.os.ZygoteInit启动Zygote进程和SystemServer进程 ;当处于非Zygote模式时,系统会调用com.android.internal.os.RuntimeInit创建应用程序的进程。
2.2 创建Zygote进程
下面,我们来分析下Zygote进程的启动过程。我们看下AndroidRuntime类的start方法的关键代码:
位置:Android源码/base/core/jni/AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const char* options) { … //加载libdvm.so JniInvocation jni_invocation; jni_invocation.Init(NULL); … //创建Dalvik虚拟机 if (startVm(&mJavaVM, &env) != 0) { return; } … //注册Android核心类的JNI方法 if (startReg(env) < 0) { ALOGE("Unable to register all android natives\n"); return; } … jclass stringClass; jobjectArray strArray; jstring classNameStr; jstring optionsStr; stringClass = env->FindClass("java/lang/String"); assert(stringClass != NULL); strArray = env->NewObjectArray(2, stringClass, NULL); assert(strArray != NULL); classNameStr = env->NewStringUTF(className); assert(classNameStr != NULL); env->SetObjectArrayElement(strArray, 0, classNameStr); optionsStr = env->NewStringUTF(options); env->SetObjectArrayElement(strArray, 1, optionsStr); //调用com.android.internal.os.ZygoteInit的main方法(进入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 { 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); } } … }
该方法主要做了4个工作:
(1) 调用jni_invocation.Init()方法加载libdvm.so,并初始化JniInvocation类的成员
(2) 调用startVM()方法创建虚拟机,并初始化BootClassloader和加载/system/framework下的jar包
(3) 调用startReg()方法注册Android核心类的JNI方法
(4) 最后,通过JNI机制进入Java层的com.android.internal.os.ZygoteInit类的main方法,然后创建Zygote进程的Server端Socket,并启动SystemServer进程。
其关键流程如下图所示:
下面我们分别对上面4个工作进一步分析。
2.2.1 加载libdvm.so
参考[7]
位置:Android源码/libnativehelper/JniInvocation.cpp
我们看下JniInvocation类下的Init方法:
… JniInvocation::JniInvocation() : handle_(NULL), JNI_GetDefaultJavaVMInitArgs_(NULL), JNI_CreateJavaVM_(NULL), JNI_GetCreatedJavaVMs_(NULL) { LOG_ALWAYS_FATAL_IF(jni_invocation_ != NULL, "JniInvocation instance already initialized"); jni_invocation_ = this; } … bool JniInvocation::Init(const char* library) { … #ifdef HAVE_ANDROID_OS static const char* kLibrarySystemProperty = "persist.sys.dalvik.vm.lib"; #endif static const char* kLibraryFallback = "libdvm.so"; bool JniInvocation::Init(const char* library) { #ifdef HAVE_ANDROID_OS char default_library[PROPERTY_VALUE_MAX]; property_get(kLibrarySystemProperty, default_library, kLibraryFallback); #else const char* default_library = kLibraryFallback; #endif if (library == NULL) { library = default_library; } … if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetDefaultJavaVMInitArgs_), "JNI_GetDefaultJavaVMInitArgs")) { return false; } if (!FindSymbol(reinterpret_cast<void**>(&JNI_CreateJavaVM_),"JNI_CreateJavaVM")) { return false; } if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetCreatedJavaVMs_),"JNI_GetCreatedJavaVMs")) { return false; } return true; }
我们首先看下JniInvocation类的定义,一共有4个成员,分别是handle_,用于保存dlopen加载libdvm.so后返回的文件句柄,以及JNI_GetDefaultJavaVMInitArgs_、JNI_CreateJavaVM_和JNI_GetCreatedJavaVMs_。
接下来继续分析Init方法。Init方法首先读取”persist.sys.dalvik.vm.lib”系统属性,该属性值可能是libdvm.so或libart.so,我们可以通过getprop命令后去persist.sys.dalvik.vm.lib属性的值,或者直接查看/system/build.prop文件。如下图,在Android4.4.3下默认还是libdvm.so,但用户可以通过在Settings=>Developer Options=>Select runtime来选择要Dalvik还是ART,如下图所示。而在Android5.0版本以后,则默认是ART。这里我们默认分析Dalvik。接下来,则调用dlopen加载libdvm.so,然后找到GetDefaultJavaVMInitArgs、CreateJavaVM和GetCreatedJavaVMs三个接口并赋值给JniInvocation类对应的3个成员。
我们可以看到,Init方法其实就是初始化JniInvocation类里面的成员,和初始化Dalvik虚拟机环境的。
获取persist.sys.dalvik.vm.lib属性的值。
TODO:了解JNI的环境
2.2.2 创建Dalvik虚拟机和初始化BootClassloader
完成JNI环境的初始化工作后,接着AndroidRuntime::start函数()调用startVM()方法创建虚拟机。我们看下startVM的代码:
位置:Android源码/base/core/jni/AndroidRuntime.cpp
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv) { … JavaVMInitArgs initArgs; JavaVMOption opt; … property_get("dalvik.vm.checkjni", propBuf, ""); … property_get("dalvik.vm.execution-mode", propBuf, ""); … property_get("dalvik.vm.stack-trace-file", stackTraceFileBuf, ""); … property_get("dalvik.vm.check-dex-sum", propBuf, ""); … property_get("dalvik.vm.heapsize", heapsizeOptsBuf+4, "16m"); … property_get("dalvik.vm.stack-trace-file", stackTraceFileBuf, ""); … if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) { … } … }
startVM方法先是读取系统属性并设置Dalvik虚拟机的各项参数,然后才调用JNI_CreateJavaVM方法真正去创建Dalvik虚拟机。这些参数我们也可以通过getprop命令去获取,如下图所示。
而JNI_CreateJavaVM方法正式livdvm.so中的函数。
位置:Android源码/dalvik/vm/jni.cpp。
jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) { … //初始化JavaVM变量 JavaVMExt* pVM = (JavaVMExt*) calloc(1, sizeof(JavaVMExt)); pVM->funcTable = &gInvokeInterface; pVM->envList = NULL; dvmInitMutex(&pVM->envListLock); … //初始化JNI环境(初始化JNIEnv变量) JNIEnvExt* pEnv = (JNIEnvExt*) dvmCreateJNIEnv(NULL); //初始化Dalvik虚拟机 gDvm.initializing = true; std::string status = dvmStartup(argc, argv.get(), args->ignoreUnrecognized, (JNIEnv*)pEnv); gDvm.initializing = false; … }
JNI_CreateJavaVM首先初始化JavaVM和JNIEnv变量,完成JNI环境的初始化工作。接着调用创建虚拟机的核心方法dvmStartup()方法。我们看下dvmStartup()方法的源码:
位置:Android源码/dalvik/vm/Init.cpp
std::string dvmStartup(int argc, const char* const argv[], bool ignoreUnrecognized, JNIEnv* pEnv) { … //解析参数 int cc = processOptions(argc, argv, ignoreUnrecognized); … //初始化BootClassLoader if (!dvmClassStartup()) { return "dvmClassStartup failed"; } }
dvmStartup首先对参数进行解析,然后做了很多其它工作,这里我们重点分析dvmClassStartup()方法,该方法初始化boot class loader,并加载bootclasspath路径下所有的jar包,也就是/system/framework下所有的类。也就是说Zygote进程加载了framework下所有的jar包,而由于app进程的创建是通过克隆Zygote进程的,所以说app也同样加载了所有的framework下的包。下图是BOOTCLASSPATH路径:
我们分析下dvmClassStartup()方法:
位置:Android源码/dalvik/vm/oo/Class.cpp
bool dvmClassStartup() { … //loadedClasses是哈希表,保存所有已经加载了的类 gDvm.loadedClasses = dvmHashTableCreate(256, (HashFreeFunc) dvmFreeClassInnards); … //加载bootclasspath路径下的所有jar包 processClassPath(gDvm.bootClassPathStr, true); … }
gDvm全局变量的loadedClasses成员是哈希表,保存了所有加载到内存中的类。
dvmClassStartup方法调用processClassPath函数进行/system/framework目录下jar包的加载工作。该方法其实就是调用加载解析dex或jar包的方法,我们会在xxx章详细介绍。
2.2.3 framework层资源加载过程
TODO:分析processClassPath加载framework资源过程
3.2.4 通过反射进入ZygoteInit类的main方法
接下来我们分析com.android.internal.os.ZygoteInit的main方法。
位置:Android源码/framework/base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String argv[]) { … registerZygoteSocket(); … if (argv[1].equals("start-system-server")) { startSystemServer(); } … runSelectLoop(); … }
该main方法主要做了3件事:
(1) 注册创建Zygote进程的Server端Socket
(2) 启动SystemServer进程
(3) 进入消息循环,监听来自AMS发送过来的创建app进程的请求
2.3 创建Zygote进程Server端监听服务
Zygote进程创建Server端Socket关键流程如下图所示:
我们从ZygoteInit类main方法的registerZygoteSocket函数源码源码开始分析:
位置:Android源码/framework/base/core/java/com/android/internal/os/ZygoteInit.java
private static void registerZygoteSocket() { if (sServerSocket == null) { int fileDesc; try { String env = System.getenv(ANDROID_SOCKET_ENV); fileDesc = Integer.parseInt(env); } catch (RuntimeException ex) { … } try { sServerSocket = new LocalServerSocket(createFileDescriptor(fileDesc)); } catch (IOException ex) { … } } }
可以看到registerZygoteSocket方法通过LocalServerSocket创建Server端Socket,并保存在ZygoteInit类的静态成员变量sServerSocket中。
接着,判断传递过来的参数是否包含”start-system-server”。我们从上面源码分析知道,Zygote启动的配置参数里面是包含该参数的。然后就调用startSystemServer来启动SystemServer进程。最后调用runSelectLoop方法进入消息循环,等待处理来自AMS发送过来的请求。
我们分析下runSelectLoop方法接收到创建app请求后的过程是怎样的。
位置:Android源码/framework/base/core/java/com/android/internal/os/ZygoteInit.java
private static void runSelectLoop() throws MethodAndArgsCaller { … while (true) { int index; … if (index < 0) { … } else if (index == 0) { … } else { boolean done; done = peers.get(index).runOnce(); i… } … } }
这里,peers.get(index)返回的是ZygoteConnection对象,runSelectLoop方法实际上调用了ZygoteConnection对象的runOnce方法做进一步的处理。
位置:Android源码/framework/base/core/java/com/android/internal/os/ZygoteConnection.java
class ZygoteConnection { … boolean runOnce() throws ZygoteInit.MethodAndArgsCaller { String args[]; Arguments parsedArgs = null; … int pid = -1; … pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo, parsedArgs.niceName); … if (pid == 0) { // in child IoUtils.closeQuietly(serverPipeFd); serverPipeFd = null; handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr); return true; } … } }
这里真正创建应用程序进程的操作是Zygote.forkAndSpecialize方法,当创建成功以后,就会调用handleChildProc来启动新创建的应用程序的进程。详细的分析我们会在3.5节讲解。
2.4 创建SystemServer进程
在3.2.3节,main入口函数调用了startSystemServer来启动SystemServer进程。SystemServer在这个过程中做了一件很重要的事情:
- 启动重要的系统服务,如ActivityManagerService、PackageManagerService、WindowManagerService等。
它创建SystemServer的关键流程如下图所示。
下面我们一个个分析这些关键函数。
位置:Android源码/framework/base/core/java/com/android/internal/os/ZygoteInit.java
private static boolean startSystemServer() throws MethodAndArgsCaller, RuntimeException { long capabilities = posixCapabilitiesAsBits( 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 */ String args[] = { "--setuid=1000", "--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); … //调用forkSystemServer方法创建SystemServer进程 pid = Zygote.forkSystemServer( parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, null, parsedArgs.permittedCapabilities, parsedArgs.effectiveCapabilities); } catch (IllegalArgumentException ex) { throw new RuntimeException(ex); } //启动SystemServer进程 if (pid == 0) { handleSystemServerProcess(parsedArgs); } return true; }
首先创建参数数组,然后传递给forkSystemServer方法并创建SystemServer进程。创建成功后,接着调用handleSystemServerProcess方法来启动SystemServer进程。
SystemServer进程启动后,就会启动各种系统服务,如AMS、PMS、WMS等。
我们接着分析handleSystemServerProcess方法。
位置:Android源码/framework/base/core/java/com/android/internal/os/ZygoteInit.java
private static void handleSystemServerProcess( ZygoteConnection.Arguments parsedArgs) throws ZygoteInit.MethodAndArgsCaller { … if (parsedArgs.invokeWith != null) { … } else { RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs); } }
handleSystemServerProcess调用RuntimeInit类的zygoteInit方法。
位置:Android源码/framework/base/core/java/com/android/internal/os/RuntimeInit.java
public static final void zygoteInit(int targetSdkVersion, String[] argv) throws ZygoteInit.MethodAndArgsCaller { if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote"); redirectLogStreams(); commonInit(); nativeZygoteInit(); applicationInit(targetSdkVersion, argv); }
这里zygoteInit调用了一个重要的方法applicationInit方法。 位置:Android源码/framework/base/core/java/com/android/internal/os/RuntimeInit.java
private static void applicationInit(int targetSdkVersion, String[] argv) throws ZygoteInit.MethodAndArgsCaller { … final Arguments args; try { args = new Arguments(argv); } catch (IllegalArgumentException ex) { … } // 调用com.android.server.SystemServer类的main方法 invokeStaticMain(args.startClass, args.startArgs); }
applicationInit调用invokeStaticMain方法通过反射的办法调用com.android.server.SystemServer类的main方法。
我们转到SystemServer类。
位置:Android源码/framework/base/services/java/com/android/server/SystemServer.java
public class SystemServer { … public static void main(String[] args) { … / Mmmmmm... more memory! dalvik.system.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); Environment.setUserRequired(true); System.loadLibrary("android_servers"); Slog.i(TAG, "Entered the Android system server!"); // Initialize native services. nativeInit(); // This used to be its own separate thread, but now it is // just the loop we run on the main thread. ServerThread thr = new ServerThread(); thr.initAndLoop(); } }
main方法创建ServerThread对象并进入消息循环。
class ServerThread { … public void initAndLoop() { … Looper.prepareMainLooper(); … context = ActivityManagerService.main(factoryTest); … pm = PackageManagerService.main(context, installer, factoryTest != SystemServer.FACTORY_TEST_OFF, onlyCore); … contentService = ContentService.main(context, factoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL); … wm = WindowManagerService.main(context, power, display, inputManager, wmHandler, factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL, !firstBoot, onlyCore); … Looper.loop(); } }
在initAndLoop方法里,通过调用各个系统服务类下的main方法创建完成关键系统服务的创建。然后调用Looper.loop()进入消息循环。
2.5 创建应用程序的进程
结合2.3中的内容,创建应用程序进程的关系如下图所示。
ActivityManagerService和Zygote进程服务端通过LocalSocket和LocalServerSocket进行进程间通信,而两者通信的媒介正式/dev/socket/zygote文件。在AMS的Client端,startProcessLocked函数是发送请求的关键函数,而Zygote进程Server端的runSelectLoop函数则是接收AMS发送过来的请求的关键方法。
回到3.1中android源码/framework/base/cmds/app_process的main函数入口,当处于非Zygote模式的时候创建的是应用程序的进程。然后通过3.3的分析我们知道,当我们点击桌面app的图标,启动一个应用程序的时候,AMS会调用startProcessLocked方法发送创建app进程的请求给Zygote进程Server端的Socket。
我们看下ActivityManagerService发送创建app进程请求的关键代码:
位置:Android源码/framework/base/services/java/com/android/server/am/ActivityManagerService.java
private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr) { … Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread", app.processName, uid, uid, gids, debugFlags, mountExternal, app.info.targetSdkVersion, app.info.seinfo, null); … }
该方法会调用Process类的start静态方法实际上是通过创建LocalSocket跟3.2.4节中Zygote进程创建的Server端Socket进行通信,而Process.start传进来的参数正是要发送给Server端要创建的应用程序的相关参数信息。
根据3.2.4节我们知道,负责接收AMS发送过来请求的是ZygoteInit类的静态成员函数runSelectLoopMode方法,该方法最终会调用Zygote.forAndSpecialize()方法创建app进程,然后调用ZygoteConnection的handleChildProc函数成员来启动该app进程。
位置:Android源码/framework/base/core/java/com/android/internal/os/ZygoteConnection.java
class ZygoteConnection { … private void handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr) throws ZygoteInit.MethodAndArgsCaller { … if (parsedArgs.runtimeInit) { if (parsedArgs.invokeWith != null) { … } else { RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs); } } … } }
这里,parsedArgs.runtimeInit为true,parsedArgs.invokeWith为null。然后调用RuntimeInit的静态成员函数zygoteInit,这一步跟创建SystemServer进程的时候是一样的,不一样的是传递过去的参数。根据3.3的分析我们知道,zygoteInit方法接着会调用applicaitonInit方法,该方法中调用了invokeStaticMain方法,同样通过反射的办法调用上面传递过来的参数,去实际调用android.app.ActivityThread类的main入口函数。
位置:Android源码/framework/base/core/java/com/android/internal/os/RuntimeInit.java
private static void applicationInit(int targetSdkVersion, String[] argv) throws ZygoteInit.MethodAndArgsCaller { … final Arguments args; try { args = new Arguments(argv); } catch (IllegalArgumentException ex) { … } // 调用android.app.ActivityThread类的main方法 invokeStaticMain(args.startClass, args.startArgs); }
从ActivityThread的main方法入口开始就是一个应用程序的启动过程。我们会在第二章的APP的启动过程做详细分析。
TODO:分析传递的参数
2.6 总结
现在我们用下面一幅图来梳理总结整个过程,对Dalvik的启动过程有一个全局的认识。
首先,Android系统在启动了init一号进程后,init进程就开始创建Zygote进程。Zygote进程主要负责两个工作:
(1) 启动SystemServer进程
(2) 创建应用程序的进程
Zygote进程在创建和初始化过程中,会调用dlopen去加载libdvm.so文件,并调用Class.cpp文件下的dvmClassStartup方法初始化BootClassloader类加载器,并加载bootclasspath,也就是/system/framework目录下的所有jar包。而由于应用程序进程的创建是通过克隆Zygote进程获得,所以,app进程中同样也加载了libdvm和/system/framework下的jar包。
然后Zygote进程会调用registerZygoteSocket()方法来创建一个Server端的Socket,然后调用runSelectLoopMode方法进入循环等待。这个Server端Socket主要负责接收ActivityManagerService发送过来的创建应用程序进程的请求,而AMS是通过调用startProcessLocked方法来发送请求的。当Zygote进程的Server端接收到来自AMS创建应用程序进程的请求后,就会调用forkAndSpecialize()方法创建。
参考:
[1] 《深入理解Android》(二)Java虚拟机Dalvik http://www.infoq.com/cn/articles/android-in-depth-dalvik
[2] Android应用启动过程解析 http://zke1ev3n.me/2015/12/02/Android-%E5%BA%94%E7%94%A8%E5%90%AF%E5%8A%A8%E8%BF%87%E7%A8%8B%E8%A7%A3%E6%9E%90/
[3]《Android系统源代码情景分析》第11、12章 Zygote和System进程的启动过程 和Android应用程序进程的启动过程http://blog.csdn.net/luoshengyang/article/details/6768304
[4]《Android Dalvivk虚拟机结构及机制剖析》第6章 Dalvik虚拟机执行流程详解
[5] Dalvik虚拟机的启动过程分析 http://blog.csdn.net/luoshengyang/article/details/8885792
[6] 理解Android虚拟机体系结构 http://android.jobbole.com/82413/
[7] Android虚拟机运行时无缝替换Dalvik虚拟机过程分析 http://blog.csdn.net/luoshengyang/article/details/18006645
[8] adb获取Android系统属性数据来源 http://blog.csdn.net/haixia_12/article/details/40857721
[9] Android应用程序进程启动过程的源代码分析 http://blog.csdn.net/luoshengyang/article/details/6747696
[10] Android进程通信套接字LocalSocket https://my.oschina.net/ososchina/blog/621761
标签:02,调用,DALVIK,虚拟机,Zygote,parsedArgs,进程,Android,android From: https://www.cnblogs.com/domefy/p/16866463.html