diff options
Diffstat (limited to 'core/jni/AndroidRuntime.cpp')
-rw-r--r-- | core/jni/AndroidRuntime.cpp | 454 |
1 files changed, 286 insertions, 168 deletions
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index ead3cbe..ab807be 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -131,7 +131,6 @@ extern int register_android_database_CursorWindow(JNIEnv* env); extern int register_android_database_SQLiteConnection(JNIEnv* env); extern int register_android_database_SQLiteGlobal(JNIEnv* env); extern int register_android_database_SQLiteDebug(JNIEnv* env); -extern int register_android_debug_JNITest(JNIEnv* env); extern int register_android_nio_utils(JNIEnv* env); extern int register_android_text_format_Time(JNIEnv* env); extern int register_android_os_Debug(JNIEnv* env); @@ -179,6 +178,7 @@ extern int register_android_content_res_Configuration(JNIEnv* env); extern int register_android_animation_PropertyValuesHolder(JNIEnv *env); extern int register_com_android_internal_content_NativeLibraryHelper(JNIEnv *env); extern int register_com_android_internal_net_NetworkStatsFactory(JNIEnv *env); +extern int register_com_android_internal_os_Zygote(JNIEnv *env); static AndroidRuntime* gCurRuntime = NULL; @@ -229,9 +229,10 @@ int register_com_android_internal_os_RuntimeInit(JNIEnv* env) /*static*/ JavaVM* AndroidRuntime::mJavaVM = NULL; - -AndroidRuntime::AndroidRuntime() : - mExitWithoutCleanup(false) +AndroidRuntime::AndroidRuntime(char* argBlockStart, const size_t argBlockLength) : + mExitWithoutCleanup(false), + mArgBlockStart(argBlockStart), + mArgBlockLength(argBlockLength) { SkGraphics::Init(); // this sets our preference for 16bit images during decode @@ -266,13 +267,17 @@ AndroidRuntime::~AndroidRuntime() return jniRegisterNativeMethods(env, className, gMethods, numMethods); } -status_t AndroidRuntime::callMain(const char* className, - jclass clazz, int argc, const char* const argv[]) +void AndroidRuntime::setArgv0(const char* argv0) { + strlcpy(mArgBlockStart, argv0, mArgBlockLength); +} + +status_t AndroidRuntime::callMain(const String8& className, jclass clazz, + const Vector<String8>& args) { JNIEnv* env; jmethodID methodId; - ALOGD("Calling main entry %s", className); + ALOGD("Calling main entry %s", className.string()); env = getJNIEnv(); if (clazz == NULL || env == NULL) { @@ -281,7 +286,7 @@ status_t AndroidRuntime::callMain(const char* className, methodId = env->GetStaticMethodID(clazz, "main", "([Ljava/lang/String;)V"); if (methodId == NULL) { - ALOGE("ERROR: could not find method %s.main(String[])\n", className); + ALOGE("ERROR: could not find method %s.main(String[])\n", className.string()); return UNKNOWN_ERROR; } @@ -292,11 +297,12 @@ status_t AndroidRuntime::callMain(const char* className, jclass stringClass; jobjectArray strArray; + const size_t numArgs = args.size(); stringClass = env->FindClass("java/lang/String"); - strArray = env->NewObjectArray(argc, stringClass, NULL); + strArray = env->NewObjectArray(numArgs, stringClass, NULL); - for (int i = 0; i < argc; i++) { - jstring argStr = env->NewStringUTF(argv[i]); + for (size_t i = 0; i < numArgs; i++) { + jstring argStr = env->NewStringUTF(args[i].string()); env->SetObjectArrayElement(strArray, i, argStr); } @@ -386,8 +392,8 @@ static void readLocale(char* language, char* region) property_get("ro.product.locale.language", propLang, "en"); property_get("ro.product.locale.region", propRegn, "US"); } - strncat(language, propLang, 2); - strncat(region, propRegn, 2); + strncat(language, propLang, 3); + strncat(region, propRegn, 3); //ALOGD("language=%s region=%s\n", language, region); } @@ -397,16 +403,16 @@ static void readLocale(char* language, char* region) * * This will cut up "extraOptsBuf" as we chop it into individual options. * + * If "quotingArg" is non-null, it is passed before each extra option in mOptions. + * * Adds the strings, if any, to mOptions. */ -void AndroidRuntime::parseExtraOpts(char* extraOptsBuf) +void AndroidRuntime::parseExtraOpts(char* extraOptsBuf, const char* quotingArg) { JavaVMOption opt; - char* start; - char* end; - memset(&opt, 0, sizeof(opt)); - start = extraOptsBuf; + char* start = extraOptsBuf; + char* end = NULL; while (*start != '\0') { while (*start == ' ') /* skip leading whitespace */ start++; @@ -420,17 +426,106 @@ void AndroidRuntime::parseExtraOpts(char* extraOptsBuf) *end++ = '\0'; /* mark end, advance to indicate more */ opt.optionString = start; + if (quotingArg != NULL) { + JavaVMOption quotingOpt; + quotingOpt.optionString = quotingArg; + mOptions.add(quotingOpt); + } mOptions.add(opt); start = end; } } /* + * Reads a "property" into "buffer" with a default of "defaultArg". If + * the property is non-empty, it is treated as a runtime option such + * as "-Xmx32m". + * + * The "runtimeArg" is a prefix for the option such as "-Xms" or "-Xmx". + * + * If an argument is found, it is added to mOptions. + * + * If an option is found, it is added to mOptions and true is + * returned. Otherwise false is returned. + */ +bool AndroidRuntime::parseRuntimeOption(const char* property, + char* buffer, + const char* runtimeArg, + const char* defaultArg) +{ + strcpy(buffer, runtimeArg); + size_t runtimeArgLen = strlen(runtimeArg); + property_get(property, buffer+runtimeArgLen, defaultArg); + if (buffer[runtimeArgLen] == '\0') { + return false; + } + + JavaVMOption opt; + memset(&opt, 0, sizeof(opt)); + + opt.optionString = buffer; + mOptions.add(opt); + + return true; +} + +/* + * Reads a "property" into "buffer". If the property is non-empty, it + * is treated as a dex2oat compiler runtime option that should be + * passed as a quoted option, e.g. "-Ximage-compiler-option + * --runtime-arg -Ximage-compiler-option -Xmx32m". + * + * The "runtimeArg" is a prefix for the option such as "-Xms" or "-Xmx". + * + * The "quotingArg" should be "-Ximage-compiler-option" or "-Xcompiler-option". + * + * If an option is found, it is added to mOptions and true is + * returned. Otherwise false is returned. + */ +bool AndroidRuntime::parseCompilerRuntimeOption(const char* property, + char* buffer, + const char* runtimeArg, + const char* quotingArg) +{ + strcpy(buffer, runtimeArg); + size_t runtimeArgLen = strlen(runtimeArg); + property_get(property, buffer+runtimeArgLen, ""); + if (buffer[runtimeArgLen] == '\0') { + return false; + } + + JavaVMOption opt; + memset(&opt, 0, sizeof(opt)); + + opt.optionString = quotingArg; + mOptions.add(opt); + + opt.optionString = "--runtime-arg"; + mOptions.add(opt); + + opt.optionString = quotingArg; + mOptions.add(opt); + + opt.optionString = buffer; + mOptions.add(opt); + + return true; +} + +/* * Start the Dalvik Virtual Machine. * * Various arguments, most determined by system properties, are passed in. * The "mOptions" vector is updated. * + * CAUTION: when adding options in here, be careful not to put the + * char buffer inside a nested scope. Adding the buffer to the + * options using mOptions.add() does not copy the buffer, so if the + * buffer goes out of scope the option may be overwritten. It's best + * to put the buffer at the top of the function so that it is more + * unlikely that someone will surround it in a scope at a later time + * and thus introduce a bug. + * * Returns 0 on success. */ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv) @@ -439,7 +534,7 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv) JavaVMInitArgs initArgs; JavaVMOption opt; char propBuf[PROPERTY_VALUE_MAX]; - char stackTraceFileBuf[PROPERTY_VALUE_MAX]; + char stackTraceFileBuf[sizeof("-Xstacktracefile:")-1 + PROPERTY_VALUE_MAX]; char dexoptFlagsBuf[PROPERTY_VALUE_MAX]; char enableAssertBuf[sizeof("-ea:")-1 + PROPERTY_VALUE_MAX]; char jniOptsBuf[sizeof("-Xjniopts:")-1 + PROPERTY_VALUE_MAX]; @@ -449,21 +544,39 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv) char heapminfreeOptsBuf[sizeof("-XX:HeapMinFree=")-1 + PROPERTY_VALUE_MAX]; char heapmaxfreeOptsBuf[sizeof("-XX:HeapMaxFree=")-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 jitcodecachesizeOptsBuf[sizeof("-Xjitcodecachesize:")-1 + PROPERTY_VALUE_MAX]; + char dalvikVmLibBuf[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 dex2oatFlagsBuf[PROPERTY_VALUE_MAX]; + char dex2oatImageFlagsBuf[PROPERTY_VALUE_MAX]; char extraOptsBuf[PROPERTY_VALUE_MAX]; - char* stackTraceFile = NULL; - bool checkJni = false; - bool checkDexSum = false; - bool logStdio = false; enum { kEMDefault, kEMIntPortable, kEMIntFast, kEMJitCompiler, } executionMode = kEMDefault; + char profilePeriod[sizeof("-Xprofile-period:")-1 + PROPERTY_VALUE_MAX]; + char profileDuration[sizeof("-Xprofile-duration:")-1 + PROPERTY_VALUE_MAX]; + char profileInterval[sizeof("-Xprofile-interval:")-1 + PROPERTY_VALUE_MAX]; + char profileBackoff[sizeof("-Xprofile-backoff:")-1 + PROPERTY_VALUE_MAX]; + char profileTopKThreshold[sizeof("-Xprofile-top-k-threshold:")-1 + PROPERTY_VALUE_MAX]; + char profileTopKChangeThreshold[sizeof("-Xprofile-top-k-change-threshold:")-1 + + PROPERTY_VALUE_MAX]; + char profileType[sizeof("-Xprofile-type:")-1 + PROPERTY_VALUE_MAX]; + char profileMaxStackDepth[sizeof("-Xprofile-max-stack-depth:")-1 + PROPERTY_VALUE_MAX]; + char langOption[sizeof("-Duser.language=") + 3]; + char regionOption[sizeof("-Duser.region=") + 3]; + char lockProfThresholdBuf[sizeof("-Xlockprofthreshold:")-1 + PROPERTY_VALUE_MAX]; + char jitOpBuf[sizeof("-Xjitop:")-1 + PROPERTY_VALUE_MAX]; + char jitMethodBuf[sizeof("-Xjitmethod:")-1 + PROPERTY_VALUE_MAX]; - + bool checkJni = false; property_get("dalvik.vm.checkjni", propBuf, ""); if (strcmp(propBuf, "true") == 0) { checkJni = true; @@ -474,6 +587,20 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv) checkJni = true; } } + ALOGD("CheckJNI is %s\n", checkJni ? "ON" : "OFF"); + if (checkJni) { + /* extended JNI checking */ + opt.optionString = "-Xcheck:jni"; + mOptions.add(opt); + + /* set a cap on JNI global references */ + opt.optionString = "-Xjnigreflimit:2000"; + mOptions.add(opt); + + /* with -Xcheck:jni, this provides a JNI function call trace */ + //opt.optionString = "-verbose:jni"; + //mOptions.add(opt); + } property_get("dalvik.vm.execution-mode", propBuf, ""); if (strcmp(propBuf, "int:portable") == 0) { @@ -484,23 +611,39 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv) executionMode = kEMJitCompiler; } - property_get("dalvik.vm.stack-trace-file", stackTraceFileBuf, ""); + parseRuntimeOption("dalvik.vm.stack-trace-file", stackTraceFileBuf, "-Xstacktracefile:"); property_get("dalvik.vm.check-dex-sum", propBuf, ""); if (strcmp(propBuf, "true") == 0) { - checkDexSum = true; + /* perform additional DEX checksum tests */ + opt.optionString = "-Xcheckdexsum"; + mOptions.add(opt); } property_get("log.redirect-stdio", propBuf, ""); if (strcmp(propBuf, "true") == 0) { - logStdio = true; + /* convert stdout/stderr to log messages */ + opt.optionString = "-Xlog-stdio"; + mOptions.add(opt); } strcpy(enableAssertBuf, "-ea:"); - property_get("dalvik.vm.enableassertions", enableAssertBuf+4, ""); + property_get("dalvik.vm.enableassertions", enableAssertBuf+sizeof("-ea:")-1, ""); + if (enableAssertBuf[sizeof("-ea:")-1] != '\0') { + /* accept "all" to mean "all classes and packages" */ + if (strcmp(enableAssertBuf+sizeof("-ea:")-1, "all") == 0) + enableAssertBuf[3] = '\0'; // truncate to "-ea" + ALOGI("Assertions enabled: '%s'\n", enableAssertBuf); + opt.optionString = enableAssertBuf; + mOptions.add(opt); + } else { + ALOGV("Assertions disabled\n"); + } strcpy(jniOptsBuf, "-Xjniopts:"); - property_get("dalvik.vm.jniopts", jniOptsBuf+10, ""); + if (parseRuntimeOption("dalvik.vm.jniopts", jniOptsBuf, "-Xjniopts:")) { + ALOGI("JNI options: '%s'\n", jniOptsBuf); + } /* route exit() to our handler */ opt.extraInfo = (void*) runtime_exit; @@ -529,54 +672,24 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv) * 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); + parseRuntimeOption("dalvik.vm.heapstartsize", heapstartsizeOptsBuf, "-Xms", "4m"); + parseRuntimeOption("dalvik.vm.heapsize", heapsizeOptsBuf, "-Xmx", "16m"); // Increase the main thread's interpreter stack size for bug 6315322. opt.optionString = "-XX:mainThreadStackSize=24K"; mOptions.add(opt); // Set the max jit code cache size. Note: size of 0 will disable the JIT. - strcpy(jitcodecachesizeOptsBuf, "-Xjitcodecachesize:"); - property_get("dalvik.vm.jit.codecachesize", jitcodecachesizeOptsBuf+19, NULL); - if (jitcodecachesizeOptsBuf[19] != '\0') { - opt.optionString = jitcodecachesizeOptsBuf; - mOptions.add(opt); - } - - strcpy(heapgrowthlimitOptsBuf, "-XX:HeapGrowthLimit="); - property_get("dalvik.vm.heapgrowthlimit", heapgrowthlimitOptsBuf+20, ""); - if (heapgrowthlimitOptsBuf[20] != '\0') { - opt.optionString = heapgrowthlimitOptsBuf; - mOptions.add(opt); - } + parseRuntimeOption("dalvik.vm.jit.codecachesize", + jitcodecachesizeOptsBuf, + "-Xjitcodecachesize:"); - strcpy(heapminfreeOptsBuf, "-XX:HeapMinFree="); - property_get("dalvik.vm.heapminfree", heapminfreeOptsBuf+16, ""); - if (heapminfreeOptsBuf[16] != '\0') { - opt.optionString = heapminfreeOptsBuf; - mOptions.add(opt); - } - - strcpy(heapmaxfreeOptsBuf, "-XX:HeapMaxFree="); - property_get("dalvik.vm.heapmaxfree", heapmaxfreeOptsBuf+16, ""); - if (heapmaxfreeOptsBuf[16] != '\0') { - opt.optionString = heapmaxfreeOptsBuf; - mOptions.add(opt); - } - - strcpy(heaptargetutilizationOptsBuf, "-XX:HeapTargetUtilization="); - property_get("dalvik.vm.heaptargetutilization", heaptargetutilizationOptsBuf+26, ""); - if (heaptargetutilizationOptsBuf[26] != '\0') { - opt.optionString = heaptargetutilizationOptsBuf; - mOptions.add(opt); - } + 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="); property_get("ro.config.low_ram", propBuf, ""); if (strcmp(propBuf, "true") == 0) { @@ -584,12 +697,8 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv) mOptions.add(opt); } - strcpy(gctypeOptsBuf, "-Xgc:"); - property_get("dalvik.vm.gctype", gctypeOptsBuf+5, ""); - if (gctypeOptsBuf[5] != '\0') { - opt.optionString = gctypeOptsBuf; - mOptions.add(opt); - } + parseRuntimeOption("dalvik.vm.gctype", gctypeOptsBuf, "-Xgc:"); + parseRuntimeOption("dalvik.vm.backgroundgctype", backgroundgcOptsBuf, "-XX:BackgroundGC="); /* * Enable or disable dexopt features, such as bytecode verification and @@ -648,49 +757,15 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv) "-agentlib:jdwp=transport=dt_android_adb,suspend=n,server=y"; mOptions.add(opt); - ALOGD("CheckJNI is %s\n", checkJni ? "ON" : "OFF"); - if (checkJni) { - /* extended JNI checking */ - opt.optionString = "-Xcheck:jni"; - mOptions.add(opt); - - /* set a cap on JNI global references */ - opt.optionString = "-Xjnigreflimit:2000"; - mOptions.add(opt); - - /* with -Xcheck:jni, this provides a JNI function call trace */ - //opt.optionString = "-verbose:jni"; - //mOptions.add(opt); - } - - char lockProfThresholdBuf[sizeof("-Xlockprofthreshold:") + sizeof(propBuf)]; - property_get("dalvik.vm.lockprof.threshold", propBuf, ""); - if (strlen(propBuf) > 0) { - strcpy(lockProfThresholdBuf, "-Xlockprofthreshold:"); - strcat(lockProfThresholdBuf, propBuf); - opt.optionString = lockProfThresholdBuf; - mOptions.add(opt); - } + parseRuntimeOption("dalvik.vm.lockprof.threshold", + lockProfThresholdBuf, + "-Xlockprofthreshold:"); /* Force interpreter-only mode for selected opcodes. Eg "1-0a,3c,f1-ff" */ - char jitOpBuf[sizeof("-Xjitop:") + PROPERTY_VALUE_MAX]; - property_get("dalvik.vm.jit.op", propBuf, ""); - if (strlen(propBuf) > 0) { - strcpy(jitOpBuf, "-Xjitop:"); - strcat(jitOpBuf, propBuf); - opt.optionString = jitOpBuf; - mOptions.add(opt); - } + parseRuntimeOption("dalvik.vm.jit.op", jitOpBuf, "-Xjitop:"); /* Force interpreter-only mode for selected methods */ - char jitMethodBuf[sizeof("-Xjitmethod:") + PROPERTY_VALUE_MAX]; - property_get("dalvik.vm.jit.method", propBuf, ""); - if (strlen(propBuf) > 0) { - strcpy(jitMethodBuf, "-Xjitmethod:"); - strcat(jitMethodBuf, propBuf); - opt.optionString = jitMethodBuf; - mOptions.add(opt); - } + parseRuntimeOption("dalvik.vm.jit.method", jitMethodBuf, "-Xjitmethod:"); if (executionMode == kEMIntPortable) { opt.optionString = "-Xint:portable"; @@ -703,54 +778,34 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv) mOptions.add(opt); } - if (checkDexSum) { - /* perform additional DEX checksum tests */ - opt.optionString = "-Xcheckdexsum"; - mOptions.add(opt); - } - - if (logStdio) { - /* convert stdout/stderr to log messages */ - opt.optionString = "-Xlog-stdio"; - mOptions.add(opt); - } - - if (enableAssertBuf[4] != '\0') { - /* accept "all" to mean "all classes and packages" */ - if (strcmp(enableAssertBuf+4, "all") == 0) - enableAssertBuf[3] = '\0'; - ALOGI("Assertions enabled: '%s'\n", enableAssertBuf); - opt.optionString = enableAssertBuf; - mOptions.add(opt); - } else { - ALOGV("Assertions disabled\n"); - } - - if (jniOptsBuf[10] != '\0') { - ALOGI("JNI options: '%s'\n", jniOptsBuf); - opt.optionString = jniOptsBuf; - mOptions.add(opt); - } - - if (stackTraceFileBuf[0] != '\0') { - static const char* stfOptName = "-Xstacktracefile:"; - - stackTraceFile = (char*) malloc(strlen(stfOptName) + - strlen(stackTraceFileBuf) +1); - strcpy(stackTraceFile, stfOptName); - strcat(stackTraceFile, stackTraceFileBuf); - opt.optionString = stackTraceFile; - mOptions.add(opt); + // libart tolerates libdvm flags, but not vice versa, so only pass some options if libart. + property_get("persist.sys.dalvik.vm.lib.2", dalvikVmLibBuf, "libart.so"); + bool libart = (strncmp(dalvikVmLibBuf, "libart", 6) == 0); + + if (libart) { + // Extra options for boot.art/boot.oat image generation. + parseCompilerRuntimeOption("dalvik.vm.image-dex2oat-Xms", dex2oatXmsImageFlagsBuf, + "-Xms", "-Ximage-compiler-option"); + parseCompilerRuntimeOption("dalvik.vm.image-dex2oat-Xmx", dex2oatXmxImageFlagsBuf, + "-Xmx", "-Ximage-compiler-option"); + property_get("dalvik.vm.image-dex2oat-flags", dex2oatImageFlagsBuf, ""); + parseExtraOpts(dex2oatImageFlagsBuf, "-Ximage-compiler-option"); + + // Extra options for DexClassLoader. + parseCompilerRuntimeOption("dalvik.vm.dex2oat-Xms", dex2oatXmsFlagsBuf, + "-Xms", "-Xcompiler-option"); + parseCompilerRuntimeOption("dalvik.vm.dex2oat-Xmx", dex2oatXmxFlagsBuf, + "-Xmx", "-Xcompiler-option"); + 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); + parseExtraOpts(extraOptsBuf, NULL); /* Set the properties for locale */ { - char langOption[sizeof("-Duser.language=") + 3]; - char regionOption[sizeof("-Duser.region=") + 3]; strcpy(langOption, "-Duser.language="); strcpy(regionOption, "-Duser.region="); readLocale(langOption, regionOption); @@ -761,6 +816,64 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv) mOptions.add(opt); } + /* + * Set profiler options + */ + if (libart) { + // Whether or not the profiler should be enabled. + property_get("dalvik.vm.profiler", propBuf, "0"); + if (propBuf[0] == '1') { + opt.optionString = "-Xenable-profiler"; + mOptions.add(opt); + } + + // Whether the profile should start upon app startup or be delayed by some random offset + // (in seconds) that is bound between 0 and a fixed value. + property_get("dalvik.vm.profile.start-immed", propBuf, "0"); + if (propBuf[0] == '1') { + opt.optionString = "-Xprofile-start-immediately"; + mOptions.add(opt); + } + + // Number of seconds during profile runs. + parseRuntimeOption("dalvik.vm.profile.period-secs", profilePeriod, "-Xprofile-period:"); + + // Length of each profile run (seconds). + parseRuntimeOption("dalvik.vm.profile.duration-secs", + profileDuration, + "-Xprofile-duration:"); + + // Polling interval during profile run (microseconds). + parseRuntimeOption("dalvik.vm.profile.interval-us", profileInterval, "-Xprofile-interval:"); + + // Coefficient for period backoff. The the period is multiplied + // by this value after each profile run. + parseRuntimeOption("dalvik.vm.profile.backoff-coeff", profileBackoff, "-Xprofile-backoff:"); + + // Top K% of samples that are considered relevant when + // deciding if the app should be recompiled. + parseRuntimeOption("dalvik.vm.profile.top-k-thr", + profileTopKThreshold, + "-Xprofile-top-k-threshold:"); + + // The threshold after which a change in the structure of the + // top K% profiled samples becomes significant and triggers + // recompilation. A change in profile is considered + // significant if X% (top-k-change-threshold) of the top K% + // (top-k-threshold property) samples has changed. + parseRuntimeOption("dalvik.vm.profile.top-k-ch-thr", + profileTopKChangeThreshold, + "-Xprofile-top-k-change-threshold:"); + + // Type of profile data. + parseRuntimeOption("dalvik.vm.profiler.type", profileType, "-Xprofile-type:"); + + // Depth of bounded stack data + parseRuntimeOption("dalvik.vm.profile.max-stack-depth", + profileMaxStackDepth, + "-Xprofile-max-stack-depth:"); + } + initArgs.version = JNI_VERSION_1_4; initArgs.options = mOptions.editArray(); initArgs.nOptions = mOptions.size(); @@ -781,7 +894,6 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv) result = 0; bail: - free(stackTraceFile); return result; } @@ -804,20 +916,23 @@ char* AndroidRuntime::toSlashClassName(const char* className) * Passes the main function two arguments, the class name and the specified * options string. */ -void AndroidRuntime::start(const char* className, const char* options) +void AndroidRuntime::start(const char* className, const Vector<String8>& options) { ALOGD("\n>>>>>> AndroidRuntime START %s <<<<<<\n", className != NULL ? className : "(unknown)"); + static const String8 startSystemServer("start-system-server"); + /* * '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))); + for (size_t i = 0; i < options.size(); ++i) { + if (options[i] == startSystemServer) { + /* 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"); @@ -858,17 +973,20 @@ void AndroidRuntime::start(const char* className, const char* options) jclass stringClass; jobjectArray strArray; jstring classNameStr; - jstring optionsStr; stringClass = env->FindClass("java/lang/String"); assert(stringClass != NULL); - strArray = env->NewObjectArray(2, 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); - optionsStr = env->NewStringUTF(options); - env->SetObjectArrayElement(strArray, 1, optionsStr); + + 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); + } /* * Start VM. This thread becomes the main thread of the VM, and will @@ -1094,7 +1212,6 @@ static void register_jam_procs(const RegJAMProc array[], size_t count) } static const RegJNIRec gRegJNI[] = { - REG_JNI(register_android_debug_JNITest), REG_JNI(register_com_android_internal_os_RuntimeInit), REG_JNI(register_android_os_SystemClock), REG_JNI(register_android_util_EventLog), @@ -1181,6 +1298,7 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_net_wifi_WifiNative), REG_JNI(register_android_os_MemoryFile), REG_JNI(register_com_android_internal_os_ZygoteInit), + REG_JNI(register_com_android_internal_os_Zygote), REG_JNI(register_android_hardware_Camera), REG_JNI(register_android_hardware_camera2_CameraMetadata), REG_JNI(register_android_hardware_SensorManager), |