summaryrefslogtreecommitdiffstats
path: root/core/jni/AndroidRuntime.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/jni/AndroidRuntime.cpp')
-rw-r--r--core/jni/AndroidRuntime.cpp454
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),