Zygote的启动流程
Init进程启动后,会加载并执行init.rc文件。该.rc文件中,就包含启动Zygote进程的Action。详见“RC文件解析”章节。
根据Zygote对应的RC文件,可知Zygote进程是由/system/bin/app_process程序来创建的。
app_process大致处理流程如下,详见“app_process解析”章节。
- 创建AppRuntime
- 整理传参,并将相应参数传给Runtime或Zygote进程。
- 使用Runtime调用start方法,传入“com.android.internal.os.ZygoteInit”类和zygote传参,启动zygote。
class AppRuntime 继承自 public AndroidRuntime。调用start方法后,将执行以下步骤。详见"AndroidRuntime解析"章节。
- 搜集JVM参数,启动VM
- 注册JNI方法。
- 利用java的反射,调用com.android.internal.os.ZygoteInit类中的main方法,创建zygote进程。
Zygote代码分析
RC文件解析
Init.rc中的Zygote内容
init.rc中涉及Zygote的部分有五处。从代码中可以看出,在初始化晚期阶段late-init,会触发Zygote-start行为,而该行为会创建zygote,以及zygote_secondary两个进程。
import /system/etc/init/hw/init.${ro.zygote}.rcimport /system/etc/init/hw/init.boringssl.${ro.zygote}.rc...on late-inittrigger zygote-start...on zygote-startwait_for_prop odsign.verification.done 1# A/B update verifier that marks a successful boot.exec_start update_verifierstart statsdstart netdstart zygotestart zygote_secondary...on userspace-reboot-resumetrigger userspace-reboot-fs-remounttrigger post-fs-datatrigger zygote-starttrigger early-boottrigger boot
关于如何启动这两个进程,可以参照init.${ro.zygote}.rc。${ro.zygote}的值,可以通过shell指令“getprop ro.zygote”获取。以下图为例,zygote64_32代表64模式为主,32位模式为辅。
init.zygote64_32.rc
引用了init.zygote64.rc
声明了一个名字为“zygote_secondary”的service。该service将有/system/bin/app_process进程来启动。其中以“-”开头的是JVM参数,-Xzygote /system/bin。以“--”开头的是进程参数,--zygote --socket-name=zygote_secondary --enable-lazy-preload。
创建了两个socket,名字为zygote_secondary和usap_pool_secondary。
import /system/etc/init/hw/init.zygote64.rcservice zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary --enable-lazy-preloadclass mainpriority -20user rootgroup root readproc reserved_disksocket zygote_secondary stream 660 root systemsocket usap_pool_secondary stream 660 root systemonrestart restart zygotetask_profiles ProcessCapacityHigh MaxPerformance
init.zygote64.rc
声明了一个名字为“zygote”的service。该service将有/system/bin/app_process进程来启动。其中以“-”开头的是JVM参数,-Xzygote /system/bin。以“--”开头的是进程参数,--zygote --start-system-server --socket-name=zygote。
创建了两个socket,名字为zygote和usap_pool_primary。
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygoteclass mainpriority -20user rootgroup root readproc reserved_disksocket zygote stream 660 root systemsocket usap_pool_primary stream 660 root systemonrestart exec_background - system system -- /system/bin/vdc volume abort_fuseonrestart write /sys/power/state on# NOTE: If the wakelock name here is changed, then also# update it in SystemSuspend.cpponrestart write /sys/power/wake_lock zygote_kwlonrestart restart audioserveronrestart restart cameraserveronrestart restart mediaonrestart restart --only-if-running media.tuneronrestart restart netdonrestart restart wificondtask_profiles ProcessCapacityHigh MaxPerformancecritical window=${zygote.critical_window.minute:-off} target=zygote-fatal
init.boringssl.zygote64_32.rc
包含的都是在某些条件下触发的自测进程。了解即可。
on init && property:ro.product.cpu.abilist32=*exec_start boringssl_self_test32
on init && property:ro.product.cpu.abilist64=*exec_start boringssl_self_test64
on property:apexd.status=ready && property:ro.product.cpu.abilist32=*exec_start boringssl_self_test_apex32
on property:apexd.status=ready && property:ro.product.cpu.abilist64=*exec_start boringssl_self_test_apex64
app_process解析
frameworks/base/cmds/app_process/app_main.cpp
int main(int argc, char* const argv[])
{if (!LOG_NDEBUG) {String8 argv_String;for (int i = 0; i < argc; ++i) {argv_String.append("\"");argv_String.append(argv[i]);argv_String.append("\" ");}ALOGV("app_process main with argv: %s", argv_String.c_str());}//步骤1:创建Runtime.--------------------------------------------AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));// Process command line arguments// ignore argv[0]argc--;argv++;// Everything up to '--' or first non '-' arg goes to the vm.//// The first argument after the VM args is the "parent dir", which// is currently unused.//// After the parent dir, we expect one or more the following internal// arguments ://// --zygote : Start in zygote mode// --start-system-server : Start the system server.// --application : Start in application (stand alone, non zygote) mode.// --nice-name : The nice name for this process.//// For non zygote starts, these arguments will be followed by// the main class name. All remaining arguments are passed to// the main method of this class.//// For zygote starts, all remaining arguments are passed to the zygote.// main function.//// Note that we must copy argument string values since we will rewrite the// entire argument block when we apply the nice name to argv0.//// As an exception to the above rule, anything in "spaced commands"// goes to the vm even though it has a space in it.const char* spaced_commands[] = { "-cp", "-classpath" };// Allow "spaced commands" to be succeeded by exactly 1 argument (regardless of -s).bool known_command = false;//步骤2:解析传参,将'-'开头的参数传给Runtime.--------------------------------------------int i;for (i = 0; i < argc; i++) {if (known_command == true) {runtime.addOption(strdup(argv[i]));// The static analyzer gets upset that we don't ever free the above// string. Since the allocation is from main, leaking it doesn't seem// problematic. NOLINTNEXTLINEALOGV("app_process main add known option '%s'", argv[i]);known_command = false;continue;}for (int j = 0;j < static_cast<int>(sizeof(spaced_commands) / sizeof(spaced_commands[0]));++j) {if (strcmp(argv[i], spaced_commands[j]) == 0) {known_command = true;ALOGV("app_process main found known command '%s'", argv[i]);}}if (argv[i][0] != '-') {break;}if (argv[i][1] == '-' && argv[i][2] == 0) {++i; // Skip --.break;}runtime.addOption(strdup(argv[i]));// The static analyzer gets upset that we don't ever free the above// string. Since the allocation is from main, leaking it doesn't seem// problematic. NOLINTNEXTLINEALOGV("app_process main add option '%s'", argv[i]);}// Parse runtime arguments. Stop at first unrecognized option.bool zygote = false;bool startSystemServer = false;bool application = false;String8 niceName;String8 className;//步骤3:整理zygote进程的传参.--------------------------------------------++i; // Skip unused "parent dir" argument.while (i < argc) {const char* arg = argv[i++];if (strcmp(arg, "--zygote") == 0) {zygote = true;niceName = ZYGOTE_NICE_NAME;} 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 if (strncmp(arg, "--", 2) != 0) {className = arg;break;} else {--i;break;}}//步骤4:根据整理的zygote传参,判断是否是zygote进程,并根据判断结果,补充“--abi-list”和“start-system-server”传参.--------------------------------------------Vector<String8> args;if (!className.empty()) {// We're not in zygote mode, the only argument we need to pass// to RuntimeInit is the application argument.//// The Remainder of args get passed to startup class main(). Make// copies of them before we overwrite them with the process name.args.add(application ? String8("application") : String8("tool"));runtime.setClassNameAndArgs(className, argc - i, argv + i);if (!LOG_NDEBUG) {String8 restOfArgs;char* const* argv_new = argv + i;int argc_new = argc - i;for (int k = 0; k < argc_new; ++k) {restOfArgs.append("\"");restOfArgs.append(argv_new[k]);restOfArgs.append("\" ");}ALOGV("Class name = %s, args = %s", className.c_str(), restOfArgs.c_str());}} else {// We're in zygote mode.maybeCreateDalvikCache();if (startSystemServer) {args.add(String8("start-system-server"));}char prop[PROP_VALUE_MAX];if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",ABI_LIST_PROPERTY);return 11;}String8 abiFlag("--abi-list=");abiFlag.append(prop);args.add(abiFlag);// In zygote mode, pass all remaining arguments to the zygote// main() method.for (; i < argc; ++i) {args.add(String8(argv[i]));}}if (!niceName.empty()) {runtime.setArgv0(niceName.c_str(), true /* setProcName */);}
//步骤5:使用runtime,调用“com.android.internal.os.ZygoteInit”类,并传入传参,启动zygote.--------------------------------------------if (zygote) {runtime.start("com.android.internal.os.ZygoteInit", args, zygote);} else if (!className.empty()) {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.");}
}
AndroidRuntime解析
frameworks/base/core/jni/AndroidRuntime.cpp
Runtime的start方法
void 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");// Whether this is the primary zygote, meaning the zygote which will fork system server.bool primary_zygote = false;//步骤1:必要的参数及环境变量检查。-----------------------------------/** 'startSystemServer == true' means runtime is obsolete and not run from* init.rc anymore, so we print out the boot start event here.*/for (size_t i = 0; i < options.size(); ++i) {if (options[i] == startSystemServer) {primary_zygote = true;/* 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)));}}const char* rootDir = getenv("ANDROID_ROOT");if (rootDir == NULL) {rootDir = "/system";if (!hasDir("/system")) {LOG_FATAL("No root directory specified, and /system does not exist.");return;}setenv("ANDROID_ROOT", rootDir, 1);}const char* artRootDir = getenv("ANDROID_ART_ROOT");if (artRootDir == NULL) {LOG_FATAL("No ART directory specified with ANDROID_ART_ROOT environment variable.");return;}const char* i18nRootDir = getenv("ANDROID_I18N_ROOT");if (i18nRootDir == NULL) {LOG_FATAL("No runtime directory specified with ANDROID_I18N_ROOT environment variable.");return;}const char* tzdataRootDir = getenv("ANDROID_TZDATA_ROOT");if (tzdataRootDir == NULL) {LOG_FATAL("No tz data directory specified with ANDROID_TZDATA_ROOT environment variable.");return;}//const char* kernelHack = getenv("LD_ASSUME_KERNEL");//ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);//步骤2:启动VM。-----------------------------------/* start the virtual machine */JniInvocation jni_invocation;jni_invocation.Init(NULL);JNIEnv* env;if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {return;}onVmCreated(env);/** Register android functions.*/
//步骤3:注册JNI方法。-----------------------------------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;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).c_str());assert(optionsStr != NULL);env->SetObjectArrayElement(strArray, i + 1, optionsStr);}//步骤4:利用java的反射,调用com.android.internal.os.ZygoteInit类中的main方法,创建zygote进程。-----------------------------------/** Start VM. This thread becomes the main thread of the VM, and will* not return until the VM exits.*/char* slashClassName = toSlashClassName(className != NULL ? 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);#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");
}
启动VM
该方法有600+行,都是收集VM参数,并调用JNI_CreateJavaVM启动VM。参数是一个可以做性能优化的点。了解即可。
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote, bool primary_zygote)
{JavaVMInitArgs initArgs;char propBuf[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 jitpthreadpriorityOptsBuf[sizeof("-Xjitpthreadpriority:")-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 jitprithreadweightOptBuf[sizeof("-Xjitprithreadweight:")-1 + PROPERTY_VALUE_MAX];char jittransitionweightOptBuf[sizeof("-Xjittransitionweight:")-1 + PROPERTY_VALUE_MAX];char hotstartupsamplesOptsBuf[sizeof("-Xps-hot-startup-method-samples:")-1 + PROPERTY_VALUE_MAX];char saveResolvedClassesDelayMsOptsBuf[sizeof("-Xps-save-resolved-classes-delay-ms:")-1 + PROPERTY_VALUE_MAX];char profileMinSavePeriodOptsBuf[sizeof("-Xps-min-save-period-ms:")-1 + PROPERTY_VALUE_MAX];char profileMinFirstSaveOptsBuf[sizeof("-Xps-min-first-save-ms:") - 1 + PROPERTY_VALUE_MAX];char profileInlineCacheThresholdOptsBuf[sizeof("-Xps-inline-cache-threshold:") - 1 + PROPERTY_VALUE_MAX];char madviseWillNeedFileSizeVdex[sizeof("-XMadviseWillNeedVdexFileSize:")-1 + PROPERTY_VALUE_MAX];char madviseWillNeedFileSizeOdex[sizeof("-XMadviseWillNeedOdexFileSize:")-1 + PROPERTY_VALUE_MAX];char madviseWillNeedFileSizeArt[sizeof("-XMadviseWillNeedArtFileSize:")-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 foregroundHeapGrowthMultiplierOptsBuf[sizeof("-XX:ForegroundHeapGrowthMultiplier=")-1 + PROPERTY_VALUE_MAX];char finalizerTimeoutMsOptsBuf[sizeof("-XX:FinalizerTimeoutMs=")-1 + PROPERTY_VALUE_MAX];char threadSuspendTimeoutOptsBuf[sizeof("-XX:ThreadSuspendTimeout=")-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 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 dex2oatCpuSetBuf[sizeof("--cpu-set=")-1 + PROPERTY_VALUE_MAX];char dex2oatCpuSetImageBuf[sizeof("--cpu-set=")-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 perfettoHprofOptBuf[sizeof("-XX:PerfettoHprof=") + PROPERTY_VALUE_MAX];char perfettoJavaHeapStackOptBuf[sizeof("-XX:PerfettoJavaHeapStackProf=") + 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 corePlatformApiPolicyBuf[sizeof("-Xcore-platform-api-policy:") + PROPERTY_VALUE_MAX];char methodTraceFileBuf[sizeof("-Xmethod-trace-file:") + PROPERTY_VALUE_MAX];char methodTraceFileSizeBuf[sizeof("-Xmethod-trace-file-size:") + PROPERTY_VALUE_MAX];std::string fingerprintBuf;char javaZygoteForkLoopBuf[sizeof("-XX:ForceJavaZygoteForkLoop=") + PROPERTY_VALUE_MAX];char jdwpProviderBuf[sizeof("-XjdwpProvider:") - 1 + PROPERTY_VALUE_MAX];char opaqueJniIds[sizeof("-Xopaque-jni-ids:") - 1 + PROPERTY_VALUE_MAX];char bootImageBuf[sizeof("-Ximage:") - 1 + PROPERTY_VALUE_MAX];// Read if we are using the profile configuration, do this at the start since the last ART args// take precedence.std::string profile_boot_class_path_flag =server_configurable_flags::GetServerConfigurableFlag(RUNTIME_NATIVE_BOOT_NAMESPACE,PROFILE_BOOT_CLASS_PATH,/*default_value=*/"");bool profile_boot_class_path;switch (ParseBool(profile_boot_class_path_flag)) {case ParseBoolResult::kError:// Default to the system property.profile_boot_class_path =GetBoolProperty("dalvik.vm.profilebootclasspath", /*default_value=*/false);break;case ParseBoolResult::kTrue:profile_boot_class_path = true;break;case ParseBoolResult::kFalse:profile_boot_class_path = false;break;}if (profile_boot_class_path) {addOption("-Xcompiler-option");addOption("--count-hotness-in-compiled-code");addOption("-Xps-profile-boot-class-path");addOption("-Xps-profile-aot-code");addOption("-Xjitsaveprofilinginfo");}std::string use_jitzygote_image_flag =server_configurable_flags::GetServerConfigurableFlag(RUNTIME_NATIVE_BOOT_NAMESPACE,ENABLE_JITZYGOTE_IMAGE,/*default_value=*/"");// Use the APEX boot image for boot class path profiling to get JIT samples on BCP methods.// Also use the APEX boot image if it's explicitly enabled via configuration flag.const bool use_apex_image = profile_boot_class_path || (use_jitzygote_image_flag == "true");if (use_apex_image) {ALOGI("Using JIT Zygote image: '%s'\n", kJitZygoteImageOption);addOption(kJitZygoteImageOption);} else if (parseRuntimeOption("dalvik.vm.boot-image", bootImageBuf, "-Ximage:")) {ALOGI("Using dalvik.vm.boot-image: '%s'\n", bootImageBuf);} else {ALOGI("Using default boot image");}std::string disable_lock_profiling =server_configurable_flags::GetServerConfigurableFlag(RUNTIME_NATIVE_BOOT_NAMESPACE,DISABLE_LOCK_PROFILING,/*default_value=*/ "");if (disable_lock_profiling == "true") {addOption(kLockProfThresholdRuntimeOption);ALOGI("Disabling lock profiling: '%s'\n", kLockProfThresholdRuntimeOption);} else {ALOGI("Leaving lock profiling enabled");}const bool checkJni = GetBoolProperty("dalvik.vm.checkjni", false);if (checkJni) {ALOGD("CheckJNI is ON");/* extended JNI checking */addOption("-Xcheck:jni");/* with -Xcheck:jni, this provides a JNI function call trace *///addOption("-verbose:jni");}const bool odsignVerificationSuccess = GetBoolProperty("odsign.verification.success", false);if (!odsignVerificationSuccess) {addOption("-Xdeny-art-apex-data-files");}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;}strcpy(jniOptsBuf, "-Xjniopts:");if (parseRuntimeOption("dalvik.vm.jniopts", jniOptsBuf, "-Xjniopts:")) {ALOGI("JNI options: '%s'\n", jniOptsBuf);}/* route exit() to our handler */addOption("exit", (void*) runtime_exit);/* route fprintf() to our handler */addOption("vfprintf", (void*) runtime_vfprintf);/* register the framework-specific "is sensitive thread" hook */addOption("sensitiveThread", (void*) runtime_isSensitiveThread);/* enable verbose; standard options are { jni, gc, class } *///addOption("-verbose:jni");addOption("-verbose:gc");//addOption("-verbose:class");// On Android, we always want to allow loading the PerfettoHprof plugin.// Even with this option set, we will still only actually load the plugin// if we are on a userdebug build or the app is debuggable or profileable.// This is enforced in art/runtime/runtime.cc.//// We want to be able to disable this, because this does not work on host,// and we do not want to enable it in tests.parseRuntimeOption("dalvik.vm.perfetto_hprof", perfettoHprofOptBuf, "-XX:PerfettoHprof=","true");// Enable PerfettoJavaHeapStackProf in the zygoteparseRuntimeOption("dalvik.vm.perfetto_javaheap", perfettoJavaHeapStackOptBuf,"-XX:PerfettoJavaHeapStackProf=", "true");if (primary_zygote) {addOption("-Xprimaryzygote");}/** The default starting and maximum size of the heap. Larger* values should be specified in a product property override.*/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=");/* Foreground heap growth multiplier option */parseRuntimeOption("dalvik.vm.foreground-heap-growth-multiplier",foregroundHeapGrowthMultiplierOptsBuf,"-XX:ForegroundHeapGrowthMultiplier=");/** Finalizer and thread suspend timeouts.*/parseRuntimeOption("dalvik.vm.finalizer-timeout-ms",finalizerTimeoutMsOptsBuf,"-XX:FinalizerTimeoutMs=");parseRuntimeOption("dalvik.vm.thread-suspend-timeout-ms",threadSuspendTimeoutOptsBuf,"-XX:ThreadSuspendTimeout=");/** JIT related options.*/parseRuntimeOption("dalvik.vm.usejit", usejitOptsBuf, "-Xusejit:");parseRuntimeOption("dalvik.vm.jitmaxsize", jitmaxsizeOptsBuf, "-Xjitmaxsize:");parseRuntimeOption("dalvik.vm.jitinitialsize", jitinitialsizeOptsBuf, "-Xjitinitialsize:");parseRuntimeOption("dalvik.vm.jitthreshold", jitthresholdOptsBuf, "-Xjitthreshold:");parseRuntimeOption("dalvik.vm.jitpthreadpriority",jitpthreadpriorityOptsBuf,"-Xjitpthreadpriority:");addOption("-Xjitsaveprofilinginfo");parseRuntimeOption("dalvik.vm.jitprithreadweight",jitprithreadweightOptBuf,"-Xjitprithreadweight:");parseRuntimeOption("dalvik.vm.jittransitionweight", jittransitionweightOptBuf,"-Xjittransitionweight:");/** Use default platform configuration as limits for madvising,* when no properties are specified.*/parseRuntimeOption("dalvik.vm.madvise.vdexfile.size",madviseWillNeedFileSizeVdex,"-XMadviseWillNeedVdexFileSize:");parseRuntimeOption("dalvik.vm.madvise.odexfile.size",madviseWillNeedFileSizeOdex,"-XMadviseWillNeedOdexFileSize:");parseRuntimeOption("dalvik.vm.madvise.artfile.size",madviseWillNeedFileSizeArt,"-XMadviseWillNeedArtFileSize:");/** Profile related options.*/parseRuntimeOption("dalvik.vm.hot-startup-method-samples", hotstartupsamplesOptsBuf,"-Xps-hot-startup-method-samples:");parseRuntimeOption("dalvik.vm.ps-resolved-classes-delay-ms", saveResolvedClassesDelayMsOptsBuf,"-Xps-save-resolved-classes-delay-ms:");parseRuntimeOption("dalvik.vm.ps-min-save-period-ms", profileMinSavePeriodOptsBuf,"-Xps-min-save-period-ms:");parseRuntimeOption("dalvik.vm.ps-min-first-save-ms", profileMinFirstSaveOptsBuf,"-Xps-min-first-save-ms:");parseRuntimeOption("dalvik.vm.ps-inline-cache-threshold", profileInlineCacheThresholdOptsBuf,"-Xps-inline-cache-threshold:");property_get("ro.config.low_ram", propBuf, "");if (strcmp(propBuf, "true") == 0) {addOption("-XX:LowMemoryMode");}/** Garbage-collection related options.*/parseRuntimeOption("dalvik.vm.gctype", gctypeOptsBuf, "-Xgc:");// If it set, honor the "enable_generational_cc" device configuration;// otherwise, let the runtime use its default behavior.std::string enable_generational_cc =server_configurable_flags::GetServerConfigurableFlag(RUNTIME_NATIVE_BOOT_NAMESPACE,ENABLE_GENERATIONAL_CC,/*default_value=*/ "");if (enable_generational_cc == "true") {addOption(kGenerationalCCRuntimeOption);} else if (enable_generational_cc == "false") {addOption(kNoGenerationalCCRuntimeOption);}parseRuntimeOption("dalvik.vm.backgroundgctype", backgroundgcOptsBuf, "-XX:BackgroundGC=");/** Enable/disable zygote native fork loop.*/parseRuntimeOption("dalvik.vm.force-java-zygote-fork-loop",javaZygoteForkLoopBuf,"-XX:ForceJavaZygoteForkLoop=");/** Enable debugging only for apps forked from zygote.*/if (zygote) {// Set the JDWP provider and required arguments. By default let the runtime choose how JDWP is// implemented. When this is not set the runtime defaults to not allowing JDWP.addOption("-XjdwpOptions:suspend=n,server=y");parseRuntimeOption("dalvik.vm.jdwp-provider",jdwpProviderBuf,"-XjdwpProvider:","default");}// Only pass an explicit opaque-jni-ids to apps forked from zygoteif (zygote) {parseRuntimeOption("dalvik.vm.opaque-jni-ids",opaqueJniIds,"-Xopaque-jni-ids:","swapable");}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");}// Extra options for JIT.parseCompilerOption("dalvik.vm.dex2oat-filter", dex2oatCompilerFilterBuf,"--compiler-filter=", "-Xcompiler-option");parseCompilerOption("dalvik.vm.dex2oat-threads", dex2oatThreadsBuf, "-j", "-Xcompiler-option");parseCompilerOption("dalvik.vm.dex2oat-cpu-set", dex2oatCpuSetBuf, "--cpu-set=","-Xcompiler-option");// Copy the variant.sprintf(dex2oat_isa_variant_key, "dalvik.vm.isa.%s.variant", ABI_STRING);parseCompilerOption(dex2oat_isa_variant_key, dex2oat_isa_variant,"--instruction-set-variant=", "-Xcompiler-option");// Copy the features.sprintf(dex2oat_isa_features_key, "dalvik.vm.isa.%s.features", ABI_STRING);parseCompilerOption(dex2oat_isa_features_key, dex2oat_isa_features,"--instruction-set-features=", "-Xcompiler-option");/** When running with debug.generate-debug-info, add --generate-debug-info to the compiler* options so that both JITted code and the boot image, if it is compiled on device, will* include native debugging information.*/property_get("debug.generate-debug-info", propBuf, "");bool generate_debug_info = (strcmp(propBuf, "true") == 0);if (generate_debug_info) {addOption("-Xcompiler-option");addOption("--generate-debug-info");}// The mini-debug-info makes it possible to backtrace through compiled code.bool generate_mini_debug_info = property_get_bool("dalvik.vm.minidebuginfo", 0);if (generate_mini_debug_info) {addOption("-Xcompiler-option");addOption("--generate-mini-debug-info");}property_get("dalvik.vm.dex2oat-flags", dex2oatFlagsBuf, "");parseExtraOpts(dex2oatFlagsBuf, "-Xcompiler-option");/* extra options; parse this late so it overrides others */property_get("dalvik.vm.extra-opts", extraOptsBuf, "");parseExtraOpts(extraOptsBuf, NULL);// Extra options for boot image generation.parseCompilerRuntimeOption("dalvik.vm.image-dex2oat-Xms", dex2oatXmsImageFlagsBuf,"-Xms", "-Ximage-compiler-option");parseCompilerRuntimeOption("dalvik.vm.image-dex2oat-Xmx", dex2oatXmxImageFlagsBuf,"-Xmx", "-Ximage-compiler-option");parseCompilerOption("dalvik.vm.image-dex2oat-filter", dex2oatImageCompilerFilterBuf,"--compiler-filter=", "-Ximage-compiler-option");// If there is a dirty-image-objects file, push it.if (hasFile("/system/etc/dirty-image-objects")) {addOption("-Ximage-compiler-option");addOption("--dirty-image-objects=/system/etc/dirty-image-objects");}parseCompilerOption("dalvik.vm.image-dex2oat-threads", dex2oatThreadsImageBuf, "-j","-Ximage-compiler-option");parseCompilerOption("dalvik.vm.image-dex2oat-cpu-set", dex2oatCpuSetImageBuf, "--cpu-set=","-Ximage-compiler-option");// The runtime may compile a boot image, when necessary, not using installd. Thus, we need// to pass the instruction-set-features/variant as an image-compiler-option.// Note: it is OK to reuse the buffer, as the values are exactly the same between// * compiler-option, used for runtime compilation (DexClassLoader)// * image-compiler-option, used for boot-image compilation on deviceparseCompilerOption(dex2oat_isa_variant_key, dex2oat_isa_variant,"--instruction-set-variant=", "-Ximage-compiler-option");parseCompilerOption(dex2oat_isa_features_key, dex2oat_isa_features,"--instruction-set-features=", "-Ximage-compiler-option");if (generate_debug_info) {addOption("-Ximage-compiler-option");addOption("--generate-debug-info");}if (generate_mini_debug_info) {addOption("-Ximage-compiler-option");addOption("--generate-mini-debug-info");}property_get("dalvik.vm.image-dex2oat-flags", dex2oatImageFlagsBuf, "");parseExtraOpts(dex2oatImageFlagsBuf, "-Ximage-compiler-option");/* Set the properties for locale */{strcpy(localeOption, "-Duser.locale=");const std::string locale = readLocale();strncat(localeOption, locale.c_str(), PROPERTY_VALUE_MAX);addOption(localeOption);}// Trace files are stored in /data/misc/trace which is writable only in debug mode.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");}}}// Native bridge library. "0" means that native bridge is disabled.//// Note: bridging is only enabled for the zygote. Other runs of// app_process may not have the permissions to mount etc.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 (zygote && 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";
#endif // defined(__LP64__)property_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);// Dalvik-cache pruning counter.parseRuntimeOption("dalvik.vm.zygote.max-boot-retry", cachePruneBuf,"-Xzygote-max-boot-retry=");// If set, the property below can be used to enable core platform API violation reporting.property_get("persist.debug.dalvik.vm.core_platform_api_policy", propBuf, "");if (propBuf[0] != '\0') {snprintf(corePlatformApiPolicyBuf,sizeof(corePlatformApiPolicyBuf),"-Xcore-platform-api-policy:%s",propBuf);addOption(corePlatformApiPolicyBuf);}/** Retrieve the build fingerprint and provide it to the runtime. That way, ANR dumps will* contain the fingerprint and can be parsed.* Fingerprints are potentially longer than PROPERTY_VALUE_MAX, so parseRuntimeOption() cannot* be used here.* Do not ever re-assign fingerprintBuf as its c_str() value is stored in mOptions.*/std::string fingerprint = GetProperty("ro.build.fingerprint", "");if (!fingerprint.empty()) {fingerprintBuf = "-Xfingerprint:" + fingerprint;addOption(fingerprintBuf.c_str());}initArgs.version = JNI_VERSION_1_4;initArgs.options = mOptions.editArray();initArgs.nOptions = mOptions.size();initArgs.ignoreUnrecognized = JNI_FALSE;/** 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");return -1;}return 0;
}
注册JNI
将gRegJNI数组里的JNI方法进行注册。RegJNIRec 包含100+个JNI方法。
/*static*/ int AndroidRuntime::startReg(JNIEnv* env)
{ATRACE_NAME("RegisterAndroidNatives");/** This hook causes all future threads created in this process to be* attached to the JavaVM. (This needs to go away in favor of JNI* Attach calls.)*/androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);ALOGV("--- registering native functions ---\n");/** Every "register" function calls one or more things that return* a local reference (e.g. FindClass). Because we haven't really* started the VM yet, they're all getting stored in the base frame* and never released. Use Push/Pop to manage the storage.*/env->PushLocalFrame(200);//核心步骤:将gRegJNI数组里的JNI方法进行注册。if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {env->PopLocalFrame(NULL);return -1;}env->PopLocalFrame(NULL);//createJavaThread("fubar", quickTest, (void*) "hello");return 0;
}
static const RegJNIRec gRegJNI[] = {REG_JNI(register_com_android_internal_os_RuntimeInit),REG_JNI(register_com_android_internal_os_ZygoteInit_nativeZygoteInit),REG_JNI(register_android_os_SystemClock),REG_JNI(register_android_util_CharsetUtils),REG_JNI(register_android_util_EventLog),REG_JNI(register_android_util_Log),REG_JNI(register_android_util_MemoryIntArray),REG_JNI(register_android_app_admin_SecurityLog),REG_JNI(register_android_content_AssetManager),REG_JNI(register_android_content_StringBlock),REG_JNI(register_android_content_XmlBlock),REG_JNI(register_android_content_res_ApkAssets),REG_JNI(register_android_content_res_ResourceTimer),REG_JNI(register_android_text_AndroidCharacter),REG_JNI(register_android_text_Hyphenator),REG_JNI(register_android_view_InputDevice),REG_JNI(register_android_view_KeyCharacterMap),REG_JNI(register_android_os_Process),REG_JNI(register_android_os_SystemProperties),REG_JNI(register_android_os_Binder),REG_JNI(register_android_os_Parcel),REG_JNI(register_android_os_PerformanceHintManager),REG_JNI(register_android_os_HidlMemory),REG_JNI(register_android_os_HidlSupport),REG_JNI(register_android_os_HwBinder),REG_JNI(register_android_os_HwBlob),REG_JNI(register_android_os_HwParcel),REG_JNI(register_android_os_HwRemoteBinder),REG_JNI(register_android_os_NativeHandle),REG_JNI(register_android_os_ServiceManager),REG_JNI(register_android_os_ServiceManagerNative),REG_JNI(register_android_os_storage_StorageManager),REG_JNI(register_android_service_DataLoaderService),REG_JNI(register_android_view_DisplayEventReceiver),REG_JNI(register_android_view_Surface),REG_JNI(register_android_view_SurfaceControl),REG_JNI(register_android_view_SurfaceControlHdrLayerInfoListener),REG_JNI(register_android_view_SurfaceSession),REG_JNI(register_android_view_InputApplicationHandle),// This must be called after register_android_view_SurfaceControl since it has a dependency// on the Java SurfaceControl object that references a native resource via static request.REG_JNI(register_android_view_InputWindowHandle),REG_JNI(register_android_view_CompositionSamplingListener),REG_JNI(register_android_view_TextureView),REG_JNI(register_android_view_TunnelModeEnabledListener),REG_JNI(register_com_google_android_gles_jni_EGLImpl),REG_JNI(register_com_google_android_gles_jni_GLImpl),REG_JNI(register_android_opengl_jni_EGL14),REG_JNI(register_android_opengl_jni_EGL15),REG_JNI(register_android_opengl_jni_EGLExt),REG_JNI(register_android_opengl_jni_GLES10),REG_JNI(register_android_opengl_jni_GLES10Ext),REG_JNI(register_android_opengl_jni_GLES11),REG_JNI(register_android_opengl_jni_GLES11Ext),REG_JNI(register_android_opengl_jni_GLES20),REG_JNI(register_android_opengl_jni_GLES30),REG_JNI(register_android_opengl_jni_GLES31),REG_JNI(register_android_opengl_jni_GLES31Ext),REG_JNI(register_android_opengl_jni_GLES32),REG_JNI(register_android_graphics_classes),REG_JNI(register_android_graphics_BLASTBufferQueue),REG_JNI(register_android_graphics_GraphicBuffer),REG_JNI(register_android_graphics_GraphicsStatsService),REG_JNI(register_android_graphics_SurfaceTexture),REG_JNI(register_android_database_CursorWindow),REG_JNI(register_android_database_SQLiteConnection),REG_JNI(register_android_database_SQLiteGlobal),REG_JNI(register_android_database_SQLiteDebug),REG_JNI(register_android_database_SQLiteRawStatement),REG_JNI(register_android_os_Debug),REG_JNI(register_android_os_FileObserver),REG_JNI(register_android_os_GraphicsEnvironment),REG_JNI(register_android_os_MessageQueue),REG_JNI(register_android_os_SELinux),REG_JNI(register_android_os_Trace),REG_JNI(register_android_os_UEventObserver),REG_JNI(register_android_net_LocalSocketImpl),REG_JNI(register_android_os_MemoryFile),REG_JNI(register_android_os_SharedMemory),REG_JNI(register_android_os_incremental_IncrementalManager),REG_JNI(register_com_android_internal_content_om_OverlayConfig),REG_JNI(register_com_android_internal_content_om_OverlayManagerImpl),REG_JNI(register_com_android_internal_net_NetworkUtilsInternal),REG_JNI(register_com_android_internal_os_ClassLoaderFactory),REG_JNI(register_com_android_internal_os_LongArrayMultiStateCounter),REG_JNI(register_com_android_internal_os_LongMultiStateCounter),REG_JNI(register_com_android_internal_os_Zygote),REG_JNI(register_com_android_internal_os_ZygoteCommandBuffer),REG_JNI(register_com_android_internal_os_ZygoteInit),REG_JNI(register_com_android_internal_security_VerityUtils),REG_JNI(register_com_android_internal_util_VirtualRefBasePtr),REG_JNI(register_android_hardware_Camera),REG_JNI(register_android_hardware_camera2_CameraMetadata),REG_JNI(register_android_hardware_camera2_DngCreator),REG_JNI(register_android_hardware_camera2_impl_CameraExtensionJpegProcessor),REG_JNI(register_android_hardware_camera2_utils_SurfaceUtils),REG_JNI(register_android_hardware_display_DisplayManagerGlobal),REG_JNI(register_android_hardware_HardwareBuffer),REG_JNI(register_android_hardware_OverlayProperties),REG_JNI(register_android_hardware_SensorManager),REG_JNI(register_android_hardware_SerialPort),REG_JNI(register_android_hardware_SyncFence),REG_JNI(register_android_hardware_UsbDevice),REG_JNI(register_android_hardware_UsbDeviceConnection),REG_JNI(register_android_hardware_UsbRequest),REG_JNI(register_android_hardware_location_ActivityRecognitionHardware),REG_JNI(register_android_media_AudioDeviceAttributes),REG_JNI(register_android_media_AudioEffectDescriptor),REG_JNI(register_android_media_AudioSystem),REG_JNI(register_android_media_AudioRecord),REG_JNI(register_android_media_AudioTrack),REG_JNI(register_android_media_AudioAttributes),REG_JNI(register_android_media_AudioProductStrategies),REG_JNI(register_android_media_AudioVolumeGroups),REG_JNI(register_android_media_AudioVolumeGroupChangeHandler),REG_JNI(register_android_media_MediaMetrics),REG_JNI(register_android_media_MicrophoneInfo),REG_JNI(register_android_media_RemoteDisplay),REG_JNI(register_android_media_ToneGenerator),REG_JNI(register_android_media_audio_common_AidlConversion),REG_JNI(register_android_media_midi),REG_JNI(register_android_opengl_classes),REG_JNI(register_android_ddm_DdmHandleNativeHeap),REG_JNI(register_android_backup_BackupDataInput),REG_JNI(register_android_backup_BackupDataOutput),REG_JNI(register_android_backup_FileBackupHelperBase),REG_JNI(register_android_backup_BackupHelperDispatcher),REG_JNI(register_android_app_backup_FullBackup),REG_JNI(register_android_app_Activity),REG_JNI(register_android_app_ActivityThread),REG_JNI(register_android_app_NativeActivity),REG_JNI(register_android_util_jar_StrictJarFile),REG_JNI(register_android_view_InputChannel),REG_JNI(register_android_view_InputEventReceiver),REG_JNI(register_android_view_InputEventSender),REG_JNI(register_android_view_InputQueue),REG_JNI(register_android_view_KeyEvent),REG_JNI(register_android_view_MotionEvent),REG_JNI(register_android_view_MotionPredictor),REG_JNI(register_android_view_PointerIcon),REG_JNI(register_android_view_VelocityTracker),REG_JNI(register_android_view_VerifiedKeyEvent),REG_JNI(register_android_view_VerifiedMotionEvent),REG_JNI(register_android_content_res_ObbScanner),REG_JNI(register_android_content_res_Configuration),REG_JNI(register_android_animation_PropertyValuesHolder),REG_JNI(register_android_security_Scrypt),REG_JNI(register_com_android_internal_content_F2fsUtils),REG_JNI(register_com_android_internal_content_NativeLibraryHelper),REG_JNI(register_com_android_internal_os_FuseAppLoop),REG_JNI(register_com_android_internal_os_KernelAllocationStats),REG_JNI(register_com_android_internal_os_KernelCpuBpfTracking),REG_JNI(register_com_android_internal_os_KernelCpuTotalBpfMapReader),REG_JNI(register_com_android_internal_os_KernelCpuUidBpfMapReader),REG_JNI(register_com_android_internal_os_KernelSingleProcessCpuThreadReader),REG_JNI(register_com_android_internal_os_KernelSingleUidTimeReader),REG_JNI(register_android_window_WindowInfosListener),REG_JNI(register_android_window_ScreenCapture),REG_JNI(register_jni_common),REG_JNI(register_android_tracing_PerfettoDataSource),REG_JNI(register_android_tracing_PerfettoDataSourceInstance),REG_JNI(register_android_tracing_PerfettoProducer),
};