首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 移动开发 > Android >

Android当地服务的启动 - zygote服务及Dalvik环境启动

2012-08-30 
Android本地服务的启动 - zygote服务及Dalvik环境启动通过上一节runtime.start方法在AndroidRuntime里实现

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运行环境就准备完毕了。

热点排行