概要
从android5.0版本开始,android应用程序默认的运行环境为ART。ART机制与Dalvik不同,在Dalvik下,应用每次运行时,字节码都需要通过即时编译器转换为机器码,这会拖慢应用的运行效率,而在ART环境下,应用在第一次安装时,字节码就会预先编译成机器码,使其成为真正的本地应用。这个过程叫做预编译(Ahead-Of-Time,AOT)。这样,应用的(首次)启动和执行就会变得更加快速。
ART的启动过程
传统的Dalvik虚拟机其实是一个Java虚拟机,只不过它执行的不是CLASS文件,而是DEX文件。因此,ART运行时最理想的方式也是实现一个Java虚拟机的形式,这样就可以很容易地将Davik虚拟机替换掉。ART运行时就是真的和Dalvik虚拟机一样,实现了一套完全兼容Java虚拟机的接口。
Dalvik虚拟机和ART虚拟机都实现了如下3个用来抽象Java虚拟机的接口。
JNI_GetDefaultJavaVMInitArgs:获取虚拟机的默认初始化参数。
JNI_CreateJavaVM:在进程中创建虚拟机实例。
JNI_GetCreatedJavaVMs:获取进程中创建的虚拟机实例。
在android系统中,Dalvik虚拟机实现在libdvm.so文件中,ART虚拟机实现在libart.so文件中。此外,android系统还提供了一个系统属性persist.sys.dalvik.vm.lib,其值等于libdvm.so或libart.so,当等于libdvm.so时,表示当前用的是Dalvik虚拟机,当用的是libart.so时,表示当前用的是ART虚拟机。
Dalvik虚拟机执行的是DEX字节码,ART虚拟机执行的是本地机器码。这意味着Dalvik虚拟机包含有一个解释器,用来执行DEX字节码。当然,android从2.2开始,也包含有JIT(Just-In-Time),用来在运行动态地将执行频率更高的DEX字节码翻译成本地机器码,然后再执行。通过JIT,就可以有效地提高Dalvik虚拟机的执行效率。但是,将DEX字节码翻译成本地机器码是发生在应用程序的运行过程中的,并且应用程序每一重新运行时,都要重新做这个翻译工作。因此,即使采用了JIT,Dalvik虚拟机的总体性能还是不能与执行本地机器码的ART虚拟机相比。
ART虚拟机在app_process进程中启动,因此,分析ART的启动过程,需要从app_process进程,也就是zygote进程入手。
运行app_process进程
当android系统启动后会创建一个zygote进程,作为应用程序的进程孵化器,并且在启动zygote进程的过程中会创建一个Dalvik虚拟机。zygote进程是通过复制自己来创建新的应用程序进程的,这意味着zygote进程会将自己的Dalvik虚拟机复制给应用程序进程。上述方式可以大大提高应用程序的启动速度,因为这种方式避免了每一个应用程序进程在启动时都要去创建一个Dalvik。事实上,zygote进程通过自我复制的方式来创建应用程序进程,省去的不仅仅是应用程序创建Dalvik虚拟机的时间,还能省去应用程序加载各种系统库和系统资源的时间,因为它们在zygote进程中已经加载过了,并且也会连同Dalvik虚拟机一起复制到应用程序中去。这也是ART优于Dalvik的原因。
12345678910111213141516171819int main(int argc, char* const argv[]) {...if (!niceName.isEmpty()) {runtime.setArgv0(niceName.string());// 此处调用set_process_name()函数,通过Linux下的pctrl系统调用把名字“app_process”换成 了“zygote”set_process_name(niceName.string());}// zygote为true代表的是zygote进程,也就是谁现在正在启动zygote进程。因为zygote进程是通过自己的资源 复制一份来fork一个新的子进程的,也就是说子进程也会进入这个文件的main函数,所以通过这个zygote变量 就可以来区分if (zygote) {runtime.start("com.android.internal.os.ZygoteInit", args, zygote);} else if (className) {runtime.start("com.android.internal.os.RuntimeInit", args, zygote);} 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;}}在上述代码中,runtime是AppRuntime的实例,AppRuntime继承自AndroidRuntime。类AndroidRuntime中的函数start()的具体实现如下。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote){ALOGD(">>>>>> START %s uid %d <<<<<<\n",className != NULL ? className : "(unknown)", getuid());static const String8 startSystemServer("start-system-server");for (size_t i = 0; i < options.size(); ++i) {if (options[i] == startSystemServer) {const int LOG_BOOT_PROGRESS_START = 3000;LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START, ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));}}const 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);}JniInvocation jni_invocation;jni_invocation.Init(NULL);JNIEnv* env;if (startVm(&mJavaVM, &env, zygote) != 0) {return;}onVmCreated(env);if (startReg(env) < 0) {ALOGE("Unable to register all android natives\n");return;}jclass stringClass;jobjectArray strArray;jstring classNameStr;stringClass = env->FindClass("java/lang/String");assert(stringClass != NULL);strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);assert(strArray != NULL);classNameStr = env->NewStringUTF(className);assert(classNameStr != NULL);env->SetObjectArrayElement(strArray, 0, classNameStr);for (size_t i = 0; i < options.size(); ++i) {jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());assert(optionsStr != NULL);env->SetObjectArrayElement(strArray, i + 1, optionsStr);}char* slashClassName = toSlashClassName(className);jclass startClass = env->FindClass(slashClassName);if (startClass == NULL) {ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);} else {jmethodID startMeth = env->GetStaticMethodID(startClass, "main","([Ljava/lang/String;)V");if (startMeth == NULL) {ALOGE("JavaVM unable to find main() in '%s'\n", className);} else {env->CallStaticVoidMethod(startClass, startMeth, strArray);if (env->ExceptionCheck())threadExitUncaughtException(env);}}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");}由此可见,类AndroidRuntime的成员函数start()最主要实现了如下3个功能。
创建一个JniInvocation实例,并且调用其成员函数Init()来初始化JNI环境。
12JniInvocation jni_invocation;jni_invocation.Init(NULL);调用AndroidRuntime类的成员函数startVM()来创建一个虚拟机及其对应的JNI接口,即创建一个JavaVM接口和一个JNIEnv接口。
12345JNIEnv* env;if (startVm(&mJavaVM, &env, zygote) != 0) {return;}onVmCreated(env);通过上述JavaVM接口和JNIEnv接口在zygote进程中加载指定的class。
其中,上述前两个功能是最关键的。因此,接下来继续分析它们所对应的函数的实现。
JniInvocation函数Init()的具体实现如下。
12345678910111213141516171819202122232425262728293031323334353637bool JniInvocation::Init(const char* library) {char buffer[PROP_VALUE_MAX];char* buffer = NULL;library = GetLibrary(library, buffer);const int kDlopenFlags = RTLD_NOW | RTLD_NODELETE;handle_ = dlopen(library, kDlopenFlags);if (handle_ == NULL) {if (strcmp(library, kLibraryFallback) == 0) {ALOGE("Failed to dlopen %s: %s", library, dlerror());return false;}ALOGW("Falling back from %s to %s after dlopen error: %s",library, kLibraryFallback, dlerror());library = kLibraryFallback;handle_ = dlopen(library, kDlopenFlags);if (handle_ == NULL) {ALOGE("Failed to dlopen %s: %s", library, dlerror());return false;}}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;}在上述代码中,函数Init()首先读取系统属性persist.sys.dalvik.vm.lib的值。因为系统属性persist.sys.dalvik.vm.lib的值等于libdvm.so或ligart.so,所以接下来就通过函数dlopen()加载到进程的是libdvm.so或ligart.so。无论加载的是哪一个,都要求导出JNI_GetDefaultJavaVMInitArgs、JNI_CreateJavaVM、JNI_GetCreatedJavaVMs这三个接口,并且分别保存在JniInvocation类的3个成员变量JNIGetDefaultJavaVMInitArgs、JNICreateJavaVM和JNIGetCreatedJavaVMs中。
准备启动
回到函数AndroidRuntime::start()的第二个功能,其主要是调用startVm()函数来启动虚拟机。AndroidRuntime类的成员函数AndroidRuntime::startVm()的具体实现代码如下。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote){JavaVMInitArgs initArgs;char propBuf[PROPERTY_VALUE_MAX];char stackTraceFileBuf[sizeof("-Xstacktracefile:")-1 + PROPERTY_VALUE_MAX];char jniOptsBuf[sizeof("-Xjniopts:")-1 + PROPERTY_VALUE_MAX];char heapstartsizeOptsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];char heapsizeOptsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX];char heapgrowthlimitOptsBuf[sizeof("-XX:HeapGrowthLimit=")-1 + PROPERTY_VALUE_MAX];char heapminfreeOptsBuf[sizeof("-XX:HeapMinFree=")-1 + PROPERTY_VALUE_MAX];char heapmaxfreeOptsBuf[sizeof("-XX:HeapMaxFree=")-1 + PROPERTY_VALUE_MAX];char usejitOptsBuf[sizeof("-Xusejit:")-1 + PROPERTY_VALUE_MAX];char jitmaxsizeOptsBuf[sizeof("-Xjitmaxsize:")-1 + PROPERTY_VALUE_MAX];char jitinitialsizeOptsBuf[sizeof("-Xjitinitialsize:")-1 + PROPERTY_VALUE_MAX];char jitthresholdOptsBuf[sizeof("-Xjitthreshold:")-1 + PROPERTY_VALUE_MAX];char useJitProfilesOptsBuf[sizeof("-Xjitsaveprofilinginfo:")-1 + PROPERTY_VALUE_MAX];char jitprithreadweightOptBuf[sizeof("-Xjitprithreadweight:")-1 + PROPERTY_VALUE_MAX];char jittransitionweightOptBuf[sizeof("-Xjittransitionweight:")-1 + PROPERTY_VALUE_MAX];char gctypeOptsBuf[sizeof("-Xgc:")-1 + PROPERTY_VALUE_MAX];char backgroundgcOptsBuf[sizeof("-XX:BackgroundGC=")-1 + PROPERTY_VALUE_MAX];char heaptargetutilizationOptsBuf[sizeof("-XX:HeapTargetUtilization=")-1 + PROPERTY_VALUE_MAX];char cachePruneBuf[sizeof("-Xzygote-max-boot-retry=")-1 + PROPERTY_VALUE_MAX];char dex2oatXmsImageFlagsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];char dex2oatXmxImageFlagsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX];char dex2oatXmsFlagsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];char dex2oatXmxFlagsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX];char dex2oatCompilerFilterBuf[sizeof("--compiler-filter=")-1 + PROPERTY_VALUE_MAX];char dex2oatImageCompilerFilterBuf[sizeof("--compiler-filter=")-1 + PROPERTY_VALUE_MAX];char dex2oatThreadsBuf[sizeof("-j")-1 + PROPERTY_VALUE_MAX];char dex2oatThreadsImageBuf[sizeof("-j")-1 + PROPERTY_VALUE_MAX];char dex2oat_isa_variant_key[PROPERTY_KEY_MAX];char dex2oat_isa_variant[sizeof("--instruction-set-variant=") -1 + PROPERTY_VALUE_MAX];char dex2oat_isa_features_key[PROPERTY_KEY_MAX];char dex2oat_isa_features[sizeof("--instruction-set-features=") -1 + PROPERTY_VALUE_MAX];char dex2oatFlagsBuf[PROPERTY_VALUE_MAX];char dex2oatImageFlagsBuf[PROPERTY_VALUE_MAX];char extraOptsBuf[PROPERTY_VALUE_MAX];char voldDecryptBuf[PROPERTY_VALUE_MAX];enum {kEMDefault,kEMIntPortable,kEMIntFast,kEMJitCompiler,} executionMode = kEMDefault;char localeOption[sizeof("-Duser.locale=") + PROPERTY_VALUE_MAX];char lockProfThresholdBuf[sizeof("-Xlockprofthreshold:")-1 + PROPERTY_VALUE_MAX];char nativeBridgeLibrary[sizeof("-XX:NativeBridge=") + PROPERTY_VALUE_MAX];char cpuAbiListBuf[sizeof("--cpu-abilist=") + PROPERTY_VALUE_MAX];char methodTraceFileBuf[sizeof("-Xmethod-trace-file:") + PROPERTY_VALUE_MAX];char methodTraceFileSizeBuf[sizeof("-Xmethod-trace-file-size:") + PROPERTY_VALUE_MAX];char fingerprintBuf[sizeof("-Xfingerprint:") + PROPERTY_VALUE_MAX];bool checkJni = false;property_get("dalvik.vm.checkjni", propBuf, "");if (strcmp(propBuf, "true") == 0) {checkJni = true;} else if (strcmp(propBuf, "false") != 0) {property_get("ro.kernel.android.checkjni", propBuf, "");if (propBuf[0] == '1') {checkJni = true;}}ALOGD("CheckJNI is %s\n", checkJni ? "ON" : "OFF");if (checkJni) {addOption("-Xcheck:jni");}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;}parseRuntimeOption("dalvik.vm.stack-trace-file", stackTraceFileBuf, "-Xstacktracefile:");strcpy(jniOptsBuf, "-Xjniopts:");if (parseRuntimeOption("dalvik.vm.jniopts", jniOptsBuf, "-Xjniopts:")) {ALOGI("JNI options: '%s'\n", jniOptsBuf);}addOption("exit", (void*) runtime_exit); // exit()线程处理addOption("vfprintf", (void*) runtime_vfprintf); // fprintf()线程处理addOption("sensitiveThread", (void*) runtime_isSensitiveThread); // 注册敏感线程框架addOption("-verbose:gc");// 默认的启动和堆的最大尺寸parseRuntimeOption("dalvik.vm.heapstartsize", heapstartsizeOptsBuf, "-Xms", "4m");parseRuntimeOption("dalvik.vm.heapsize", heapsizeOptsBuf, "-Xmx", "16m");parseRuntimeOption("dalvik.vm.heapgrowthlimit", heapgrowthlimitOptsBuf, "-XX:HeapGrowthLimit=");parseRuntimeOption("dalvik.vm.heapminfree", heapminfreeOptsBuf, "-XX:HeapMinFree=");parseRuntimeOption("dalvik.vm.heapmaxfree", heapmaxfreeOptsBuf, "-XX:HeapMaxFree=");parseRuntimeOption("dalvik.vm.heaptargetutilization",heaptargetutilizationOptsBuf,"-XX:HeapTargetUtilization=");// 设置最大JIT代码缓存大小parseRuntimeOption("dalvik.vm.usejit", usejitOptsBuf, "-Xusejit:");parseRuntimeOption("dalvik.vm.jitmaxsize", jitmaxsizeOptsBuf, "-Xjitmaxsize:");parseRuntimeOption("dalvik.vm.jitinitialsize", jitinitialsizeOptsBuf, "-Xjitinitialsize:");parseRuntimeOption("dalvik.vm.jitthreshold", jitthresholdOptsBuf, "-Xjitthreshold:");property_get("dalvik.vm.usejitprofiles", useJitProfilesOptsBuf, "");if (strcmp(useJitProfilesOptsBuf, "true") == 0) {addOption("-Xjitsaveprofilinginfo");}parseRuntimeOption("dalvik.vm.jitprithreadweight",jitprithreadweightOptBuf,"-Xjitprithreadweight:");parseRuntimeOption("dalvik.vm.jittransitionweight",jittransitionweightOptBuf,"-Xjittransitionweight:");property_get("ro.config.low_ram", propBuf, "");if (strcmp(propBuf, "true") == 0) {addOption("-XX:LowMemoryMode");}parseRuntimeOption("dalvik.vm.gctype", gctypeOptsBuf, "-Xgc:");parseRuntimeOption("dalvik.vm.backgroundgctype", backgroundgcOptsBuf, "-XX:BackgroundGC=");if (zygote) {addOption("-agentlib:jdwp=transport=dt_android_adb,suspend=n,server=y");}parseRuntimeOption("dalvik.vm.lockprof.threshold",lockProfThresholdBuf,"-Xlockprofthreshold:");if (executionMode == kEMIntPortable) {addOption("-Xint:portable");} else if (executionMode == kEMIntFast) {addOption("-Xint:fast");} else if (executionMode == kEMJitCompiler) {addOption("-Xint:jit");}property_get("vold.decrypt", voldDecryptBuf, "");bool skip_compilation = ((strcmp(voldDecryptBuf, "trigger_restart_min_framework") == 0) ||(strcmp(voldDecryptBuf, "1") == 0));parseCompilerRuntimeOption("dalvik.vm.image-dex2oat-Xms", dex2oatXmsImageFlagsBuf,"-Xms", "-Ximage-compiler-option");parseCompilerRuntimeOption("dalvik.vm.image-dex2oat-Xmx", dex2oatXmxImageFlagsBuf,"-Xmx", "-Ximage-compiler-option");if (skip_compilation) {addOption("-Ximage-compiler-option");addOption("--compiler-filter=verify-none");} else {parseCompilerOption("dalvik.vm.image-dex2oat-filter", dex2oatImageCompilerFilterBuf,"--compiler-filter=", "-Ximage-compiler-option");}if (!hasFile("/system/etc/preloaded-classes")) {ALOGE("Missing preloaded-classes file, /system/etc/preloaded-classes not found: %s\n",strerror(errno));return -1;}addOption("-Ximage-compiler-option");addOption("--image-classes=/system/etc/preloaded-classes");if (hasFile("/system/etc/compiled-classes")) {addOption("-Ximage-compiler-option");addOption("--compiled-classes=/system/etc/compiled-classes");}property_get("dalvik.vm.image-dex2oat-flags", dex2oatImageFlagsBuf, "");parseExtraOpts(dex2oatImageFlagsBuf, "-Ximage-compiler-option");parseCompilerRuntimeOption("dalvik.vm.dex2oat-Xms", dex2oatXmsFlagsBuf,"-Xms", "-Xcompiler-option");parseCompilerRuntimeOption("dalvik.vm.dex2oat-Xmx", dex2oatXmxFlagsBuf,"-Xmx", "-Xcompiler-option");if (skip_compilation) {addOption("-Xcompiler-option");addOption("--compiler-filter=verify-none");addOption("--runtime-arg");addOption("-Xnorelocate");} else {parseCompilerOption("dalvik.vm.dex2oat-filter", dex2oatCompilerFilterBuf,"--compiler-filter=", "-Xcompiler-option");}parseCompilerOption("dalvik.vm.dex2oat-threads", dex2oatThreadsBuf, "-j", "-Xcompiler-option");parseCompilerOption("dalvik.vm.image-dex2oat-threads", dex2oatThreadsImageBuf, "-j","-Ximage-compiler-option");constexpr const char* instruction_set = "arm";constexpr const char* instruction_set = "arm64";constexpr const char* instruction_set = "mips";constexpr const char* instruction_set = "mips64";constexpr const char* instruction_set = "x86";constexpr const char* instruction_set = "x86_64";constexpr const char* instruction_set = "unknown";sprintf(dex2oat_isa_variant_key, "dalvik.vm.isa.%s.variant", instruction_set);parseCompilerOption(dex2oat_isa_variant_key, dex2oat_isa_variant,"--instruction-set-variant=", "-Ximage-compiler-option");parseCompilerOption(dex2oat_isa_variant_key, dex2oat_isa_variant,"--instruction-set-variant=", "-Xcompiler-option");sprintf(dex2oat_isa_features_key, "dalvik.vm.isa.%s.features", instruction_set);parseCompilerOption(dex2oat_isa_features_key, dex2oat_isa_features,"--instruction-set-features=", "-Ximage-compiler-option");parseCompilerOption(dex2oat_isa_features_key, dex2oat_isa_features,"--instruction-set-features=", "-Xcompiler-option");property_get("dalvik.vm.dex2oat-flags", dex2oatFlagsBuf, "");parseExtraOpts(dex2oatFlagsBuf, "-Xcompiler-option");property_get("dalvik.vm.extra-opts", extraOptsBuf, "");parseExtraOpts(extraOptsBuf, NULL);{strcpy(localeOption, "-Duser.locale=");const std::string locale = readLocale();strncat(localeOption, locale.c_str(), PROPERTY_VALUE_MAX);addOption(localeOption);}property_get("ro.debuggable", propBuf, "0");if (strcmp(propBuf, "1") == 0) {property_get("dalvik.vm.method-trace", propBuf, "false");if (strcmp(propBuf, "true") == 0) {addOption("-Xmethod-trace");parseRuntimeOption("dalvik.vm.method-trace-file",methodTraceFileBuf,"-Xmethod-trace-file:");parseRuntimeOption("dalvik.vm.method-trace-file-siz",methodTraceFileSizeBuf,"-Xmethod-trace-file-size:");property_get("dalvik.vm.method-trace-stream", propBuf, "false");if (strcmp(propBuf, "true") == 0) {addOption("-Xmethod-trace-stream");}}}property_get("ro.dalvik.vm.native.bridge", propBuf, "");if (propBuf[0] == '\0') {ALOGW("ro.dalvik.vm.native.bridge is not expected to be empty");} else if (strcmp(propBuf, "0") != 0) {snprintf(nativeBridgeLibrary, sizeof("-XX:NativeBridge=") + PROPERTY_VALUE_MAX,"-XX:NativeBridge=%s", propBuf);addOption(nativeBridgeLibrary);}if defined(LP64)const char* cpu_abilist_property_name = "ro.product.cpu.abilist64";elseconst char* cpu_abilist_property_name = "ro.product.cpu.abilist32";endifproperty_get(cpu_abilist_property_name, propBuf, "");if (propBuf[0] == '\0') {ALOGE("%s is not expected to be empty", cpu_abilist_property_name);return -1;}snprintf(cpuAbiListBuf, sizeof(cpuAbiListBuf), "--cpu-abilist=%s", propBuf);addOption(cpuAbiListBuf);parseRuntimeOption("dalvik.vm.zygote.max-boot-retry", cachePruneBuf,"-Xzygote-max-boot-retry=");property_get("debug.generate-debug-info", propBuf, "");if (strcmp(propBuf, "true") == 0) {addOption("-Xcompiler-option");addOption("--generate-debug-info");addOption("-Ximage-compiler-option");addOption("--generate-debug-info");}parseRuntimeOption("ro.build.fingerprint", fingerprintBuf, "-Xfingerprint:");initArgs.version = JNI_VERSION_1_4;initArgs.options = mOptions.editArray();initArgs.nOptions = mOptions.size();initArgs.ignoreUnrecognized = JNI_FALSE;// 初始化VMif (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {ALOGE("JNI_CreateJavaVM failed\n");return -1;}return 0;}由上述实现代码可知,函数AndroidRuntime::startVM()最终会调用JNI_CreateJavaVM()函数,其具体实现代码如下。
123extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {return JniInvocation::GetJniInvocation().JNI_CreateJavaVM(p_vm, p_env, vm_args);}123jint JniInvocation::JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {return JNI_CreateJavaVM_(p_vm, p_env, vm_args);}123456789101112131415161718192021222324252627282930313233extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {ScopedTrace trace(__FUNCTION__);const JavaVMInitArgs* args = static_cast<JavaVMInitArgs*>(vm_args);if (IsBadJniVersion(args->version)) {LOG(ERROR) << "Bad JNI version passed to CreateJavaVM: " << args->version;return JNI_EVERSION;}RuntimeOptions options;for (int i = 0; i < args->nOptions; ++i) {JavaVMOption* option = &args->options[i];options.push_back(std::make_pair(std::string(option->optionString), option->extraInfo));}bool ignore_unrecognized = args->ignoreUnrecognized;if (!Runtime::Create(options, ignore_unrecognized)) {return JNI_ERR;}android::InitializeNativeLoader();// 获取Runtime当前实例,Runtime使用单例模式实现Runtime* runtime = Runtime::Current();// 调用start()函数bool started = runtime->Start();if (!started) {delete Thread::Current()->GetJniEnv();delete runtime->GetJavaVM();LOG(WARNING) << "CreateJavaVM failed";return JNI_ERR;}*p_env = Thread::Current()->GetJniEnv();*p_vm = runtime->GetJavaVM();return JNI_OK;}类JniInvocation的静态成员函数GetJniInvocation()返回的便是前面所创建的JniInvocation实例。有了这个实例后,就继续调用其成员函数JNI_CreateJavaVM()来创建一个JavaVM接口及其对应的JNIEnv接口。类JniInvocation的成员变量JNICreateJavaVM指向的就是前面所加载的libdvm.so或libart.so所导出的函数JNI_CreateJavaVM()。
创建运行实例
在文件 art/runtime/java_vm_ext.cc中,函数JNI_CreateJavaVM()会调用函数Create()创建Runtime的实例。
12345bool Runtime::Create(const RuntimeOptions& raw_options, bool ignore_unrecognized) {RuntimeArgumentMap runtime_options;return ParseOptions(raw_options, ignore_unrecognized, &runtime_options) &&Create(std::move(runtime_options));}Create()函数调用ParseOptions(raw_options, ignore_unrecognized, &runtime_options)函数和Create(std::move(runtime_options)函数。
1234567891011bool Runtime::ParseOptions(const RuntimeOptions& raw_options,bool ignore_unrecognized,RuntimeArgumentMap* runtime_options) {InitLogging(/* argv */ nullptr); // 初始化Log系统bool parsed = ParsedOptions::Parse(raw_options, ignore_unrecognized, runtime_options);if (!parsed) {LOG(ERROR) << "Failed to parse options";return false;}return true;}123456789101112bool Runtime::Create(RuntimeArgumentMap&& runtime_options) {if (Runtime::instance_ != nullptr) {return false;}instance_ = new Runtime; // 创建Runtime实例// 初始化Runtimeif (!instance_->Init(std::move(runtime_options))) {instance_ = nullptr;return false;}return true;}函数JNI_CreateJavaVM()获取当前Runtime实例后,会调用start()函数,其具体实现如下。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899bool Runtime::Start() {VLOG(startup) << "Runtime::Start entering";CHECK(!no_sig_chain_) << "A started runtime should have sig chain enabled";#if defined(__linux__) && !defined(__ANDROID__) && defined(__x86_64__)if (kIsDebugBuild) {CHECK_EQ(prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY), 0);}#endif// 获取当前运行线程Thread* self = Thread::Current();self->TransitionFromRunnableToSuspended(kNative);started_ = true;if (jit_options_->UseJitCompilation() || jit_options_->GetSaveProfilingInfo()) {std::string error_msg;if (!IsZygote()) {CreateJit();} else if (jit_options_->UseJitCompilation()) {if (!jit::Jit::LoadCompilerLibrary(&error_msg)) {LOG(WARNING) << "Failed to load JIT compiler with error " << error_msg;}}}if (!IsImageDex2OatEnabled() || !GetHeap()->HasBootImageSpace()) {ScopedObjectAccess soa(self);StackHandleScope<2> hs(soa.Self());auto class_class(hs.NewHandle<mirror::Class>(mirror::Class::GetJavaLangClass()));auto field_class(hs.NewHandle<mirror::Class>(mirror::Field::StaticClass()));class_linker_->EnsureInitialized(soa.Self(), class_class, true, true);class_linker_->EnsureInitialized(soa.Self(), field_class, true, true);}{ScopedTrace trace2("InitNativeMethods");// 完成Native函数的初始化工作InitNativeMethods();}InitThreadGroups(self);Thread::FinishStartup();system_class_loader_ = CreateSystemClassLoader(this);if (is_zygote_) {if (!InitZygote()) {return false;}} else {if (is_native_bridge_loaded_) {PreInitializeNativeBridge(".");}NativeBridgeAction action = force_native_bridge_? NativeBridgeAction::kInitialize: NativeBridgeAction::kUnload;InitNonZygoteOrPostFork(self->GetJniEnv(),/* is_system_server */ false,action,GetInstructionSetString(kRuntimeISA));}StartDaemonThreads();{ScopedObjectAccess soa(self);self->GetJniEnv()->locals.AssertEmpty();}VLOG(startup) << "Runtime::Start exiting";finished_starting_ = true;if (profiler_options_.IsEnabled() && !profile_output_filename_.empty()) {int fd = open(profile_output_filename_.c_str(), O_RDWR|O_CREAT|O_EXCL, 0660);if (fd >= 0) {close(fd);} else if (errno != EEXIST) {LOG(WARNING) << "Failed to access the profile file. Profiler disabled.";}}if (trace_config_.get() != nullptr && trace_config_->trace_file != "") {ScopedThreadStateChange tsc(self, kWaitingForMethodTracingStart);Trace::Start(trace_config_->trace_file.c_str(),-1,static_cast<int>(trace_config_->trace_file_size),0,trace_config_->trace_output_mode,trace_config_->trace_mode,0);}return true;}接下来看看InitNativeMethods()函数的具体实现。
123456789101112131415161718192021222324252627282930313233void Runtime::InitNativeMethods() {VLOG(startup) << "Runtime::InitNativeMethods entering";Thread* self = Thread::Current();JNIEnv* env = self->GetJniEnv(); // 获取JNI环境CHECK_EQ(self->GetState(), kNative);JniConstants::init(env);RegisterRuntimeNativeMethods(env); // 完成Native函数的注册WellKnownClasses::Init(env);{std::string error_msg;if (!java_vm_->LoadNativeLibrary(env, "libjavacore.so", nullptr, nullptr, &error_msg)) {LOG(FATAL) << "LoadNativeLibrary failed for \"libjavacore.so\": " << error_msg;}}{constexpr const char* kOpenJdkLibrary = kIsDebugBuild? "libopenjdkd.so": "libopenjdk.so";std::string error_msg;if (!java_vm_->LoadNativeLibrary(env, kOpenJdkLibrary, nullptr, nullptr, &error_msg)) {LOG(FATAL) << "LoadNativeLibrary failed for \"" << kOpenJdkLibrary << "\": " << error_msg;}}WellKnownClasses::LateInit(env);VLOG(startup) << "Runtime::InitNativeMethods exiting";}注册本地JNI函数
在文件 art/runtime/runtime.cc中的函数Runtime::InitNativeMethods()中,通过调用RegisterRuntimeNativeMethods(env)来注册Native函数,其具体实现如下。
1234567891011121314151617181920212223242526272829void Runtime::RegisterRuntimeNativeMethods(JNIEnv* env) {register_dalvik_system_DexFile(env);register_dalvik_system_VMDebug(env);register_dalvik_system_VMRuntime(env);register_dalvik_system_VMStack(env);register_dalvik_system_ZygoteHooks(env);register_java_lang_Class(env);register_java_lang_DexCache(env);register_java_lang_Object(env);register_java_lang_ref_FinalizerReference(env);register_java_lang_reflect_AbstractMethod(env);register_java_lang_reflect_Array(env);register_java_lang_reflect_Constructor(env);register_java_lang_reflect_Field(env);register_java_lang_reflect_Method(env);register_java_lang_reflect_Proxy(env);register_java_lang_ref_Reference(env);register_java_lang_String(env);register_java_lang_StringFactory(env);register_java_lang_System(env);register_java_lang_Thread(env);register_java_lang_Throwable(env);register_java_lang_VMClassLoader(env);register_java_util_concurrent_atomic_AtomicLong(env);register_libcore_util_CharsetUtils(env);register_org_apache_harmony_dalvik_ddmc_DdmServer(env);register_org_apache_harmony_dalvik_ddmc_DdmVmInternal(env);register_sun_misc_Unsafe(env);}在上述代码中列出了需要注册的函数列表。
启动守护进程
再次返回到Runtime::Start函数,其中调用InitZygote完成一些文件系统的mount工作。然后通过StartDaemonThreads()代码行调用java.lang.Daemons.start()函数启动守护进程,其具体实现如下。
123456789101112131415161718void Runtime::StartDaemonThreads() {ScopedTrace trace(__FUNCTION__);VLOG(startup) << "Runtime::StartDaemonThreads entering";Thread* self = Thread::Current();CHECK_EQ(self->GetState(), kNative);JNIEnv* env = self->GetJniEnv();env->CallStaticVoidMethod(WellKnownClasses::java_lang_Daemons,WellKnownClasses::java_lang_Daemons_start);if (env->ExceptionCheck()) {env->ExceptionDescribe();LOG(FATAL) << "Error starting java.lang.Daemons";}VLOG(startup) << "Runtime::StartDaemonThreads exiting";}综上所述,android系统通过将ART运行时抽象成一个Java虚拟机,以及通过系统属性persist.sys.dalvik.vm.lib和一个适配层JniInvocation,就可以无缝地将Dalvik虚拟机替换成ART运行时。这个替换过程设计非常巧妙,因为涉及的代码修改非常少。
解析参数
在函数JNI_CreateJavaVM()中,现调用Create()函数创建Runtime。Runtime是一个单例,创建后会马上调用/art/runtime/runtime.cc中的Init()函数。Init()函数的功能是解析参数,初始化Heap和JavaVMExt结构,实现线程和信号处理,并创建ClassLinker等。函数Init()的具体实现代码如下。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) {RuntimeArgumentMap runtime_options(std::move(runtime_options_in));ScopedTrace trace(__FUNCTION__);CHECK_EQ(sysconf(_SC_PAGE_SIZE), kPageSize);MemMap::Init();using Opt = RuntimeArgumentMap;VLOG(startup) << "Runtime::Init -verbose:startup enabled";QuasiAtomic::Startup();oat_file_manager_ = new OatFileManager;Thread::SetSensitiveThreadHook(runtime_options.GetOrDefault(Opt::HookIsSensitiveThread));Monitor::Init(runtime_options.GetOrDefault(Opt::LockProfThreshold));boot_class_path_string_ = runtime_options.ReleaseOrDefault(Opt::BootClassPath);class_path_string_ = runtime_options.ReleaseOrDefault(Opt::ClassPath);properties_ = runtime_options.ReleaseOrDefault(Opt::PropertiesList);compiler_callbacks_ = runtime_options.GetOrDefault(Opt::CompilerCallbacksPtr);patchoat_executable_ = runtime_options.ReleaseOrDefault(Opt::PatchOat);must_relocate_ = runtime_options.GetOrDefault(Opt::Relocate);is_zygote_ = runtime_options.Exists(Opt::Zygote);is_explicit_gc_disabled_ = runtime_options.Exists(Opt::DisableExplicitGC);dex2oat_enabled_ = runtime_options.GetOrDefault(Opt::Dex2Oat);image_dex2oat_enabled_ = runtime_options.GetOrDefault(Opt::ImageDex2Oat);dump_native_stack_on_sig_quit_ = runtime_options.GetOrDefault(Opt::DumpNativeStackOnSigQuit);vfprintf_ = runtime_options.GetOrDefault(Opt::HookVfprintf);exit_ = runtime_options.GetOrDefault(Opt::HookExit);abort_ = runtime_options.GetOrDefault(Opt::HookAbort);default_stack_size_ = runtime_options.GetOrDefault(Opt::StackSize);stack_trace_file_ = runtime_options.ReleaseOrDefault(Opt::StackTraceFile);compiler_executable_ = runtime_options.ReleaseOrDefault(Opt::Compiler);compiler_options_ = runtime_options.ReleaseOrDefault(Opt::CompilerOptions);image_compiler_options_ = runtime_options.ReleaseOrDefault(Opt::ImageCompilerOptions);image_location_ = runtime_options.GetOrDefault(Opt::Image);max_spins_before_thin_lock_inflation_ =runtime_options.GetOrDefault(Opt::MaxSpinsBeforeThinLockInflation);// 初始化Monitor(相当于mutex + conditional variable,可用于多个线程同步)和线程链表monitor_list_ = new MonitorList;monitor_pool_ = MonitorPool::Create();thread_list_ = new ThreadList;intern_table_ = new InternTable;verify_ = runtime_options.GetOrDefault(Opt::Verify);allow_dex_file_fallback_ = !runtime_options.Exists(Opt::NoDexFileFallback);no_sig_chain_ = runtime_options.Exists(Opt::NoSigChain);force_native_bridge_ = runtime_options.Exists(Opt::ForceNativeBridge);Split(runtime_options.GetOrDefault(Opt::CpuAbiList), ',', &cpu_abilist_);fingerprint_ = runtime_options.ReleaseOrDefault(Opt::Fingerprint);if (runtime_options.GetOrDefault(Opt::Interpret)) {GetInstrumentation()->ForceInterpretOnly();}zygote_max_failed_boots_ = runtime_options.GetOrDefault(Opt::ZygoteMaxFailedBoots);experimental_flags_ = runtime_options.GetOrDefault(Opt::Experimental);is_low_memory_mode_ = runtime_options.Exists(Opt::LowMemoryMode);{CompilerFilter::Filter filter;std::string filter_str = runtime_options.GetOrDefault(Opt::OatFileManagerCompilerFilter);if (!CompilerFilter::ParseCompilerFilter(filter_str.c_str(), &filter)) {LOG(ERROR) << "Cannot parse compiler filter " << filter_str;return false;}OatFileManager::SetCompilerFilter(filter);}XGcOption xgc_option = runtime_options.GetOrDefault(Opt::GcOption);// 实现比较重 要的Heap以及GC的初始化工作heap_ = new gc::Heap(runtime_options.GetOrDefault(Opt::MemoryInitialSize),runtime_options.GetOrDefault(Opt::HeapGrowthLimit),runtime_options.GetOrDefault(Opt::HeapMinFree),runtime_options.GetOrDefault(Opt::HeapMaxFree),runtime_options.GetOrDefault(Opt::HeapTargetUtilization),runtime_options.GetOrDefault(Opt::ForegroundHeapGrowthMultiplier),runtime_options.GetOrDefault(Opt::MemoryMaximumSize),runtime_options.GetOrDefault(Opt::NonMovingSpaceCapacity),runtime_options.GetOrDefault(Opt::Image),runtime_options.GetOrDefault(Opt::ImageInstructionSet),xgc_option.collector_type_,runtime_options.GetOrDefault(Opt::BackgroundGc),runtime_options.GetOrDefault(Opt::LargeObjectSpace),runtime_options.GetOrDefault(Opt::LargeObjectThreshold),runtime_options.GetOrDefault(Opt::ParallelGCThreads),runtime_options.GetOrDefault(Opt::ConcGCThreads),runtime_options.Exists(Opt::LowMemoryMode),runtime_options.GetOrDefault(Opt::LongPauseLogThreshold),runtime_options.GetOrDefault(Opt::LongGCLogThreshold),runtime_options.Exists(Opt::IgnoreMaxFootprint),runtime_options.GetOrDefault(Opt::UseTLAB),xgc_option.verify_pre_gc_heap_,xgc_option.verify_pre_sweeping_heap_,xgc_option.verify_post_gc_heap_,xgc_option.verify_pre_gc_rosalloc_,xgc_option.verify_pre_sweeping_rosalloc_,xgc_option.verify_post_gc_rosalloc_,xgc_option.gcstress_,runtime_options.GetOrDefault(Opt::EnableHSpaceCompactForOOM),runtime_options.GetOrDefault(Opt::HSpaceCompactForOOMMinIntervalsMs));if (!heap_->HasBootImageSpace() && !allow_dex_file_fallback_) {LOG(ERROR) << "Dex file fallback disabled, cannot continue without image.";return false;}dump_gc_performance_on_shutdown_ = runtime_options.Exists(Opt::DumpGCPerformanceOnShutdown);if (runtime_options.Exists(Opt::JdwpOptions)) {Dbg::ConfigureJdwp(runtime_options.GetOrDefault(Opt::JdwpOptions));}jit_options_.reset(jit::JitOptions::CreateFromRuntimeArguments(runtime_options));if (IsAotCompiler()) {jit_options_->SetUseJitCompilation(false);jit_options_->SetSaveProfilingInfo(false);}lambda_box_table_ = MakeUnique<lambda::BoxTable>();const bool use_malloc = IsAotCompiler();arena_pool_.reset(new ArenaPool(use_malloc, /* low_4gb */ false));jit_arena_pool_.reset(new ArenaPool(/* use_malloc */ false, /* low_4gb */ false, "CompilerMetadata"));if (IsAotCompiler() && Is64BitInstructionSet(kRuntimeISA)) {low_4gb_arena_pool_.reset(new ArenaPool(/* use_malloc */ false, /* low_4gb */ true));}linear_alloc_.reset(CreateLinearAlloc());BlockSignals();InitPlatformSignalHandlers();switch (kRuntimeISA) {case kArm:case kThumb2:case kX86:case kArm64:case kX86_64:case kMips:case kMips64:implicit_null_checks_ = true;implicit_so_checks_ = !(RUNNING_ON_MEMORY_TOOL && kMemoryToolIsValgrind);break;default:break;}if (!no_sig_chain_) {InitializeSignalChain();if (implicit_null_checks_ || implicit_so_checks_ || implicit_suspend_checks_) {fault_manager.Init();if (implicit_suspend_checks_) {new SuspensionHandler(&fault_manager);}if (implicit_so_checks_) {new StackOverflowHandler(&fault_manager);}if (implicit_null_checks_) {new NullPointerHandler(&fault_manager);}if (kEnableJavaStackTraceHandler) {new JavaStackTraceHandler(&fault_manager);}}}java_vm_ = new JavaVMExt(this, runtime_options);Thread::Startup();Thread* self = Thread::Attach("main", false, nullptr, false);CHECK_EQ(self->GetThreadId(), ThreadList::kMainThreadId);CHECK(self != nullptr);self->TransitionFromSuspendedToRunnable();GetHeap()->EnableObjectValidation();CHECK_GE(GetHeap()->GetContinuousSpaces().size(), 1U);// ClassLinker的初始化操作class_linker_ = new ClassLinker(intern_table_);...VLOG(startup) << "Runtime::Init exiting";return true;}在文件 art/runtime/runtime.cc中,通过函数Runtime::ParseOptions()解析参数,将raw_options中的参数传入ParsedOptions::Parse()进一步调用ParsedOptions的Parse()函数来解析,其具体实现在parsed_options.cc中。
12345678bool ParsedOptions::Parse(const RuntimeOptions& options,bool ignore_unrecognized,RuntimeArgumentMap* runtime_options) {CHECK(runtime_options != nullptr);ParsedOptions parser;return parser.DoParse(options, ignore_unrecognized, runtime_options);}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151bool ParsedOptions::DoParse(const RuntimeOptions& options,bool ignore_unrecognized,RuntimeArgumentMap* runtime_options) {for (size_t i = 0; i < options.size(); ++i) {if (true && options[0].first == "-Xzygote") {LOG(INFO) << "option[" << i << "]=" << options[i].first;}}auto parser = MakeParser(ignore_unrecognized);std::vector<std::string> argv_list;if (!ProcessSpecialOptions(options, nullptr, &argv_list)) {return false;}CmdlineResult parse_result = parser->Parse(argv_list);if (parse_result.IsError()) {if (parse_result.GetStatus() == CmdlineResult::kUsage) {UsageMessage(stdout, "%s\n", parse_result.GetMessage().c_str());Exit(0);} else if (parse_result.GetStatus() == CmdlineResult::kUnknown && !ignore_unrecognized) {Usage("%s\n", parse_result.GetMessage().c_str());return false;} else {Usage("%s\n", parse_result.GetMessage().c_str());Exit(0);}UNREACHABLE();}using M = RuntimeArgumentMap;RuntimeArgumentMap args = parser->ReleaseArgumentsMap();if (args.Exists(M::Help)) {Usage(nullptr);return false;} else if (args.Exists(M::ShowVersion)) {UsageMessage(stdout, "ART version %s\n", Runtime::GetVersion());Exit(0);} else if (args.Exists(M::BootClassPath)) {LOG(INFO) << "setting boot class path to " << *args.Get(M::BootClassPath);}if (args.GetOrDefault(M::UseJitCompilation) && args.GetOrDefault(M::Interpret)) {Usage("-Xusejit:true and -Xint cannot be specified together");Exit(0);}if (getenv("BOOTCLASSPATH") != nullptr) {args.SetIfMissing(M::BootClassPath, std::string(getenv("BOOTCLASSPATH")));}if (getenv("CLASSPATH") != nullptr) {args.SetIfMissing(M::ClassPath, std::string(getenv("CLASSPATH")));}args.SetIfMissing(M::ParallelGCThreads, gc::Heap::kDefaultEnableParallelGC ?static_cast<unsigned int>(sysconf(_SC_NPROCESSORS_CONF) - 1u) : 0u);{LogVerbosity *log_verbosity = args.Get(M::Verbose);if (log_verbosity != nullptr) {gLogVerbosity = *log_verbosity;}}MaybeOverrideVerbosity();Trace::SetDefaultClockSource(args.GetOrDefault(M::ProfileClock));if (!ProcessSpecialOptions(options, &args, nullptr)) {return false;}{gc::CollectorType background_collector_type_;gc::CollectorType collector_type_ = (XGcOption{}).collector_type_; // NOLINTbool low_memory_mode_ = args.Exists(M::LowMemoryMode);background_collector_type_ = args.GetOrDefault(M::BackgroundGc);{XGcOption* xgc = args.Get(M::GcOption);if (xgc != nullptr && xgc->collector_type_ != gc::kCollectorTypeNone) {collector_type_ = xgc->collector_type_;}}if (background_collector_type_ == gc::kCollectorTypeNone) {if (collector_type_ != gc::kCollectorTypeGSS) {background_collector_type_ = low_memory_mode_ ?gc::kCollectorTypeSS : gc::kCollectorTypeHomogeneousSpaceCompact;} else {background_collector_type_ = collector_type_;}}args.Set(M::BackgroundGc, BackgroundGcOption { background_collector_type_ });}std::string core_jar("/core.jar");std::string core_libart_jar("/core-libart.jar");std::string core_jar("/core-hostdex.jar");std::string core_libart_jar("/core-libart-hostdex.jar");auto boot_class_path_string = args.GetOrDefault(M::BootClassPath);size_t core_jar_pos = boot_class_path_string.find(core_jar);if (core_jar_pos != std::string::npos) {boot_class_path_string.replace(core_jar_pos, core_jar.size(), core_libart_jar);args.Set(M::BootClassPath, boot_class_path_string);}{auto&& boot_class_path = args.GetOrDefault(M::BootClassPath);auto&& boot_class_path_locations = args.GetOrDefault(M::BootClassPathLocations);if (args.Exists(M::BootClassPathLocations)) {size_t boot_class_path_count = ParseStringList<':'>::Split(boot_class_path).Size();if (boot_class_path_count != boot_class_path_locations.Size()) {Usage("The number of boot class path files does not match"" the number of boot class path locations given\n"" boot class path files (%zu): %s\n"" boot class path locations (%zu): %s\n",boot_class_path.size(), boot_class_path_string.c_str(),boot_class_path_locations.Size(), boot_class_path_locations.Join().c_str());return false;}}}if (!args.Exists(M::CompilerCallbacksPtr) && !args.Exists(M::Image)) {std::string image = GetAndroidRoot();image += "/framework/boot.art";args.Set(M::Image, image);}if (args.GetOrDefault(M::HeapGrowthLimit) <= 0u ||args.GetOrDefault(M::HeapGrowthLimit) > args.GetOrDefault(M::MemoryMaximumSize)) {args.Set(M::HeapGrowthLimit, args.GetOrDefault(M::MemoryMaximumSize));}if (args.GetOrDefault(M::Experimental) & ExperimentalFlags::kLambdas) {LOG(WARNING) << "Experimental lambdas have been enabled. All lambda opcodes have "<< "an unstable specification and are nearly guaranteed to change over time. "<< "Do not attempt to write shipping code against these opcodes.";}*runtime_options = std::move(args);return true;}主要是对环境变量BOOTCLASSPATH和CLASSPATH进行处理。
执行完Runtime中的函数Create()和Init()后,在JNI_CreateJavaVM()函数中Runtime的Start()函数会被调用。
初始化类、方法和域
在文件runtime.cc的函数InitNativeMethods()中分别调用函数JniConstants::init(env)和WellKnownClasses::Init(env)。这两个函数通过FindClass()、GetStaticFieldID()和GetStaticMethodID()等函数初始化了系统基本类、方法和域,这些都是最基本的类。然后RegisterRuntimeNativeMethods(env)函数注册了系统类中的Native函数。接着函数InitNativeMethods会载入libjavacore.so库,单独载入是因为该库本身包含了System.loadLibrary()实现,不先载入会导致顺序紊乱。
再次回到Runtime::Start()函数进行线程初始化,再判断是否为zygote线程。如果是则调用InitZygote()进行初始化操作,否则调用InitNonZygoteOrPostFork()函数。最后Start()函数中调用了StartDaemonThreads()函数,此函数的作用是调用Java类的Daemons的start()方法来启动一些Daemons进程,这个过程实际上和Dalvik启动时完成的最后一项工作相同。
从startVM()返回后,AndroidRuntime执行startReg()在创建线程时加一个hook()函数,这样每个Thread启动时会先去执行AndroidRuntime::javaThreadShell(),而该函数会初始化Java虚拟机环境,这样新建的线程就可以调用Java层了。
进入main()函数
完成ART的基本初始化工作后,接下来开始执行主函数,具体步骤如下所示:
- 先通过FindClass()找到相应的类。
- 然后通过GetStaticMethodID()找到相应的方法。
- 最后调用CallStaticVoidMethod()进入Java执行托管代码工作。
这里以Zygote初始化操作为例进行分析,其中,类名为com.android.internal.os.ZygoteInit,方法为main。在AndroidRuntime::start中调用startVM()启动虚拟机,然后调用startReg()注册JNI方法,并调用com.android.internal.os.ZygoteInit类的main()函数。
|
|
|
|
|
|
|
|
总结
ART优点
- 系统性能的显著提升
- 应用启动更快、运行更快、体验更流畅、触感反馈更及时
- 更长的电池续航能力
- 支持更低的硬件
ART缺点
- 更大的存储空间占用,可能会增加10%~20%
- 更长的应用安装时间
总的来说ART的功效就是“空间换时间”。