【分析】dalvik虚拟机启动过程(一)

源码版本:Android-4.4.4_r2

提示:大部分分析直接注释在代码内。

主要函数的调用层次:

|AndroidRuntime::start|AndroidRuntime::startVm|JNI_CreateJavaVM|dvmCreateJNIEnv|dvmStartup|dvmThreadStartup|pthread_key_create|dvmAllocBitVector|allocThread|prepareThread|assignThreadId|dvmAllocBit|setThreadSelf|AndroidRuntime::startReg|androidSetCreateThreadFunc|register_jni_procs

AndroidRuntime::start路径:frameworks/base/core/jni/AndroidRuntime.cpp/** * 启动 Android 运行时。这个函数参与虚拟机的启动和 * 调用 "className" 指定的Java类中的 "static void main(String[] args)" 方法。 * * Passes the main function two arguments, the class name and the specified * options string. * * 当启动zygote时,framework/base/cmds/app_process/app_main.cpp中的的main函数会传入下面的参数: * className:"com.android.internal.os.ZygoteInit" * options:如果启动systemserver则会传入"start-system-server",否则将会传入一个空字符串。 */void AndroidRuntime::start(const char* className, const char* options){ALOGD("\n>>>>>> AndroidRuntime START %s <<<<<<\n",className != NULL ? className : "(unknown)");/** 'startSystemServer == true' means runtime is obsolete and not run from* init.rc anymore, so we print out the boot start event here.*/if (strcmp(options, "start-system-server") == 0) {/* track our progress through the boot sequence */const int LOG_BOOT_PROGRESS_START = 3000;LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));}// 获得/设置环境变量ANDROID_ROOTconst char* rootDir = getenv("ANDROID_ROOT");if (rootDir == NULL) {rootDir = "/system";if (!hasDir("/system")) {LOG_FATAL("No root directory specified, and /android does not exist.");return;}setenv("ANDROID_ROOT", rootDir, 1);}//const char* kernelHack = getenv("LD_ASSUME_KERNEL");//ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);/* 启动虚拟机。 */JniInvocation jni_invocation;jni_invocation.Init(NULL);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;}/** We want to call main() with a String array with arguments in it.* At present we have two arguments, the class name and an option string.* Create an array to hold them.*/jclass stringClass;jobjectArray strArray;jstring classNameStr;jstring optionsStr;// String[] strArray = new String[2];stringClass = env->FindClass("java/lang/String");assert(stringClass != NULL);strArray = env->NewObjectArray(2, stringClass, NULL);assert(strArray != NULL);// strArray[0] = classNameStr;classNameStr = env->NewStringUTF(className);assert(classNameStr != NULL);env->SetObjectArrayElement(strArray, 0, classNameStr);// strArray[1] = optionsStr;optionsStr = env->NewStringUTF(options);env->SetObjectArrayElement(strArray, 1, optionsStr);// 至此,参数数组包含了两个元素,第一个是类名,第二个是选项字符串。/** Start VM. This thread becomes the main thread of the VM, and will* not return until the VM exits.*/char* slashClassName = toSlashClassName(className); // 将Java风格的类路径转换为jni风格的类路径。jclass startClass = env->FindClass(slashClassName);if (startClass == NULL) {ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);/* keep going */} else {// 调用Java类中的main方法。// startClass.main(strArray)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 {// 调用main方法。env->CallStaticVoidMethod(startClass, startMeth, strArray);#if 0if (env->ExceptionCheck())threadExitUncaughtException(env);#endif}}free(slashClassName);ALOGD("Shutting down VM\n");if (mJavaVM->DetachCurrentThread() != JNI_OK)ALOGW("Warning: unable to detach main thread\n");if (mJavaVM->DestroyJavaVM() != 0)ALOGW("Warning: VM did not shut down cleanly\n");}上面的代码中调用了Android::startVm函数启动了虚拟机:/* * 启动 Dalvik 虚拟机。 * * Various arguments, most determined by system properties, are passed in. * The "mOptions" vector is updated. * * 返回 0 代表成功。 */int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv){……// checkjni就是我们在C++层调用jni函数的时候,会对参数或者什么的进行检查,// 要是不合法的话,直接把虚拟机exit!第一个影响速度,第二个是影响程序,这个只作为开发时候使用。// 但是开启这个标志也有显著的好处,如果jni程序有问题,,那么可以准确的爆出是哪里的问题!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;}}// 虚拟机模式。property_get("dalvik.vm.execution-mode", propBuf, "");if (strcmp(propBuf, "int:portable") == 0) {executionMode = kEMIntPortable;} else if (strcmp(propBuf, "int:fast") == 0) {executionMode = kEMIntFast;} else if (strcmp(propBuf, "int:jit") == 0) {executionMode = kEMJitCompiler;}……/** 设置虚拟机最大heapsize。貌似最大才给16m设置的有点少。* The default starting and maximum size of the heap. Larger* values should be specified in a product property override.*/strcpy(heapstartsizeOptsBuf, "-Xms");property_get("dalvik.vm.heapstartsize", heapstartsizeOptsBuf+4, "4m");opt.optionString = heapstartsizeOptsBuf;mOptions.add(opt);strcpy(heapsizeOptsBuf, "-Xmx");property_get("dalvik.vm.heapsize", heapsizeOptsBuf+4, "16m");opt.optionString = heapsizeOptsBuf;mOptions.add(opt);// Increase the main thread's interpreter stack size for bug 6315322.opt.optionString = "-XX:mainThreadStackSize=24K";mOptions.add(opt);……/** We don't have /tmp on the device, but we often have an SD card. Apps* shouldn't use this, but some test suites might want to exercise it.*/opt.optionString = "-Djava.io.tmpdir=/sdcard";mOptions.add(opt);initArgs.version = JNI_VERSION_1_4;initArgs.options = mOptions.editArray();initArgs.nOptions = mOptions.size();initArgs.ignoreUnrecognized = JNI_FALSE;/** 具体dalvik虚拟机有哪些参数,可以参考Dalvik的说明,* 反正调用了下面这个函数,虚拟机就按您指定的参数启动了。* Initialize the VM.** The JavaVM* is essentially per-process, and the JNIEnv* is per-thread.* If this call succeeds, the VM is ready, and we can start issuing* JNI calls.*/if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {ALOGE("JNI_CreateJavaVM failed\n");goto bail;}result = 0;bail:free(stackTraceFile);return result;}上面的代码中获得了大量属性设置,和做了一些检查。上面的mOptions成员变量的类型是Vector<JavaVMOption>。JavaVMOption结构体:心有多大,舞台就有多大。

【分析】dalvik虚拟机启动过程(一)

相关文章:

你感兴趣的文章:

标签云: