Android本地服务的启动 - zygote服务及Dalvik环境启动
通过上一节
runtime.start方法在AndroidRuntime里实现:
859 void AndroidRuntime::start(const char* className, const bool startSystemServer)
860 {
861 LOGD("\n>>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<<\n"); // logcat里最显眼的字样
862
863 char* slashClassName = NULL;
864 char* cp;
865 JNIEnv* env;
866
867 blockSigpipe();
868
869 /*
870 * 'startSystemServer == true' means runtime is obslete and not run from
871 * init.rc anymore, so we print out the boot start event here.
872 */
873 if (startSystemServer) {
874 /* track our progress through the boot sequence */
875 const int LOG_BOOT_PROGRESS_START = 3000;
876 LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,
877 ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
878 }
880 const char* rootDir = getenv("ANDROID_ROOT"); // 取得Android的根目录:/system
881 if (rootDir == NULL) {
882 rootDir = "/system";
883 if (!hasDir("/system")) {
884 LOG_FATAL("No root directory specified, and /android does not exist.");
885 goto bail;
886 }
887 setenv("ANDROID_ROOT", rootDir, 1);
888 }
889
890 //const char* kernelHack = getenv("LD_ASSUME_KERNEL");
891 //LOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);
892
893 /* start the virtual machine */
// 启动Dalvik虚拟机,在AndroidRuntime::startVm方法中,设备了大量VM的参数,最后调用JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs),通过JNI启动虚拟机
894 if (startVm(&mJavaVM, &env) != 0)
895 goto bail;
896
897 /*
898 * Register android functions.
899 */
900 if (startReg(env) < 0) { // 注册系统使用的JNI函数
901 LOGE("Unable to register all android natives\n");
902 goto bail;
903 }
910 jclass stringClass;
911 jobjectArray strArray;
912 jstring classNameStr;
913 jstring startSystemServerStr;
914
915 stringClass = env->FindClass("java/lang/String"); // 从Dalvik虚拟机里,查找到String类,
916 assert(stringClass != NULL);
917 strArray = env->NewObjectArray(2, stringClass, NULL); // 创建一个String数组,有两个元素(strArray = new String[2])
918 assert(strArray != NULL);
919 classNameStr = env->NewStringUTF(className); // 创建一个Java String对象,初始值为:className,其实是start第一个参数:com.android.internal.os.ZygoteInit
920 assert(classNameStr != NULL);
921 env->SetObjectArrayElement(strArray, 0, classNameStr); // 设置strArray 第一个元素的值为:classNameStr (strArray[0] =classNameStr)
922 startSystemServerStr = env->NewStringUTF(startSystemServer ?
923 "true" : "false"); // 创建一个Java String对象,初始值为:startSystemServer ,其实是start第二个参数:true
924 env->SetObjectArrayElement(strArray, 1, startSystemServerStr); // 设置strArray 第二个元素的值为:strArray[1] =startSystemServerStr
925
926 /*
927 * Start VM. This thread becomes the main thread of the VM, and will
928 * not return until the VM exits.
929 */
// 根据上面的解释可知:准备启动Java VM,并且创建VM的主线程,只要VM不退出,这个主线程一直运行。
930 jclass startClass;
931 jmethodID startMeth;
933 slashClassName = strdup(className);
934 for (cp = slashClassName; *cp != '\0'; cp++) // 将com.android.internal.os.ZygoteInit中的包分隔符‘.’换成‘/’即:com/android/internal/os/ZygoteInit
935 if (*cp == '.')
936 *cp = '/';
937
938 startClass = env->FindClass(slashClassName); // 从VM中查找ZygoteInit类,难道它要在VM里加载这个类。。。。
939 if (startClass == NULL) {
940 LOGE("JavaVM unable to locate class '%s'\n", slashClassName);
941 /* keep going */
942 } else {
943 startMeth = env->GetStaticMethodID(startClass, "main",
944 "([Ljava/lang/String;)V"); // 查找到com/android/internal/os/ZygoteInit类中的main方法ID,接合Java文件命名规则,你能更深刻的理解,为什么主类名要和文件名一致,并且main方法为static方法。
945 if (startMeth == NULL) {
946 LOGE("JavaVM unable to find main() in '%s'\n", className);
947 /* keep going */
948 } else {
949 env->CallStaticVoidMethod(startClass, startMeth, strArray); // 调用ZygoteInit类里的main方法,这不是运行ZygoteInit这个JAVA程序吗!!
950
951 #if 0
952 if (env->ExceptionCheck())
953 threadExitUncaughtException(env);
954 #endif
955 }
956 }
957
958 LOGD("Shutting down VM\n");
959 if (mJavaVM->DetachCurrentThread() != JNI_OK)
960 LOGW("Warning: unable to detach main thread\n");
961 if (mJavaVM->DestroyJavaVM() != 0)
962 LOGW("Warning: VM did not shut down cleanly\n");
963
964 bail:
965 free(slashClassName);
966 }
967
由上面的分析可知,AndroidRuntime::start方法实现了下面功能:
1> 通过startVm来启动虚拟机,并且注册了一些系统JNI函数,由于这个时候VM里还没有程序,只是个空的VM执行环境
2> 通过AndroidRuntime::start的参数,在JNI代码里构建第一个Java程序ZygoteInit,将其作为VM的主线程,同时给其传递两个JNI构建的参数:
"com/android/internal/os/ZygoteInit"和"true"
总结:
Android系统的启动是由init进程加载并启动了里面的/system/bin/app_process程序作为zygote服务,然后在zygote服务里执行runtime.start启动Dalvik虚拟机,加载了ZygoteInit类作为Dalvik虚拟机的第一个主线程。至此,Android的Java运行环境就准备完毕了。