2 * Copyright (C) 2008 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 * Dalvik initialization, shutdown, and command-line argument processing.
21 #include "test/Test.h"
22 #include "mterp/Mterp.h"
33 #define kMinHeapStartSize (1*1024*1024)
34 #define kMinHeapSize (2*1024*1024)
35 #define kMaxHeapSize (1*1024*1024*1024)
38 * Register VM-agnostic native methods for system classes.
40 extern int jniRegisterSystemMethods(JNIEnv* env);
43 static bool registerSystemNatives(JNIEnv* pEnv);
44 static bool initJdwp(void);
45 static bool initZygote(void);
49 struct DvmGlobals gDvm;
51 /* JIT-specific global state */
53 struct DvmJitGlobals gDvmJit;
55 #if defined(WITH_JIT_TUNING)
57 * Track the number of hits in the inline cache for predicted chaining.
58 * Use an ugly global variable here since it is accessed in assembly code.
68 * We follow the tradition of unhyphenated compound words.
70 static void usage(const char* progName)
72 dvmFprintf(stderr, "%s: [options] class [argument ...]\n", progName);
73 dvmFprintf(stderr, "%s: [options] -jar file.jar [argument ...]\n",progName);
74 dvmFprintf(stderr, "\n");
75 dvmFprintf(stderr, "The following standard options are recognized:\n");
76 dvmFprintf(stderr, " -classpath classpath\n");
77 dvmFprintf(stderr, " -Dproperty=value\n");
78 dvmFprintf(stderr, " -verbose:tag ('gc', 'jni', or 'class')\n");
79 dvmFprintf(stderr, " -ea[:<package name>... |:<class name>]\n");
80 dvmFprintf(stderr, " -da[:<package name>... |:<class name>]\n");
81 dvmFprintf(stderr, " (-enableassertions, -disableassertions)\n");
82 dvmFprintf(stderr, " -esa\n");
83 dvmFprintf(stderr, " -dsa\n");
85 " (-enablesystemassertions, -disablesystemassertions)\n");
86 dvmFprintf(stderr, " -showversion\n");
87 dvmFprintf(stderr, " -help\n");
88 dvmFprintf(stderr, "\n");
89 dvmFprintf(stderr, "The following extended options are recognized:\n");
90 dvmFprintf(stderr, " -Xrunjdwp:<options>\n");
91 dvmFprintf(stderr, " -Xbootclasspath:bootclasspath\n");
92 dvmFprintf(stderr, " -Xcheck:tag (e.g. 'jni')\n");
93 dvmFprintf(stderr, " -XmsN (min heap, must be multiple of 1K, >= 1MB)\n");
94 dvmFprintf(stderr, " -XmxN (max heap, must be multiple of 1K, >= 2MB)\n");
95 dvmFprintf(stderr, " -XssN (stack size, >= %dKB, <= %dKB)\n",
96 kMinStackSize / 1024, kMaxStackSize / 1024);
97 dvmFprintf(stderr, " -Xverify:{none,remote,all}\n");
98 dvmFprintf(stderr, " -Xrs\n");
101 " -Xint (extended to accept ':portable', ':fast' and ':jit')\n");
104 " -Xint (extended to accept ':portable' and ':fast')\n");
106 dvmFprintf(stderr, "\n");
107 dvmFprintf(stderr, "These are unique to Dalvik:\n");
108 dvmFprintf(stderr, " -Xzygote\n");
109 dvmFprintf(stderr, " -Xdexopt:{none,verified,all}\n");
110 dvmFprintf(stderr, " -Xnoquithandler\n");
112 " -Xjnigreflimit:N (must be multiple of 100, >= 200)\n");
113 dvmFprintf(stderr, " -Xjniopts:{warnonly,forcecopy}\n");
114 dvmFprintf(stderr, " -Xjnitrace:substring (eg NativeClass or nativeMethod)\n");
115 dvmFprintf(stderr, " -Xdeadlockpredict:{off,warn,err,abort}\n");
116 dvmFprintf(stderr, " -Xstacktracefile:<filename>\n");
117 dvmFprintf(stderr, " -Xgc:[no]precise\n");
118 dvmFprintf(stderr, " -Xgc:[no]preverify\n");
119 dvmFprintf(stderr, " -Xgc:[no]postverify\n");
120 dvmFprintf(stderr, " -Xgc:[no]concurrent\n");
121 dvmFprintf(stderr, " -Xgc:[no]verifycardtable\n");
122 dvmFprintf(stderr, " -XX:+DisableExplicitGC\n");
123 dvmFprintf(stderr, " -Xgenregmap\n");
124 dvmFprintf(stderr, " -Xverifyopt:[no]checkmon\n");
125 dvmFprintf(stderr, " -Xcheckdexsum\n");
126 #if defined(WITH_JIT)
127 dvmFprintf(stderr, " -Xincludeselectedop\n");
128 dvmFprintf(stderr, " -Xjitop:hexopvalue[-endvalue]"
129 "[,hexopvalue[-endvalue]]*\n");
130 dvmFprintf(stderr, " -Xincludeselectedmethod\n");
131 dvmFprintf(stderr, " -Xjitthreshold:decimalvalue\n");
132 dvmFprintf(stderr, " -Xjitblocking\n");
133 dvmFprintf(stderr, " -Xjitmethod:signature[,signature]* "
134 "(eg Ljava/lang/String\\;replace)\n");
135 dvmFprintf(stderr, " -Xjitcheckcg\n");
136 dvmFprintf(stderr, " -Xjitverbose\n");
137 dvmFprintf(stderr, " -Xjitprofile\n");
138 dvmFprintf(stderr, " -Xjitdisableopt\n");
140 dvmFprintf(stderr, "\n");
141 dvmFprintf(stderr, "Configured with:"
145 #ifdef WITH_HPROF_STACK
148 #ifdef WITH_MONITOR_TRACKING
151 #ifdef WITH_DEADLOCK_PREDICTION
152 " deadlock_prediction"
154 #ifdef WITH_TRACKREF_CHECKS
157 #ifdef WITH_INSTR_CHECKS
160 #ifdef WITH_EXTRA_OBJECT_VALIDATION
161 " extra_object_validation"
163 #ifdef WITH_EXTRA_GC_CHECKS
166 #if !defined(NDEBUG) && defined(WITH_DALVIK_ASSERT)
169 #ifdef WITH_JNI_STACK_CHECK
178 #ifdef PROFILE_FIELD_ACCESS
179 " profile_field_access"
181 #if defined(WITH_JIT)
182 " jit(" ARCH_VARIANT ")"
184 #if defined(WITH_SELF_VERIFICATION)
190 #ifdef WITH_INLINE_PROFILING
194 #ifdef DVM_SHOW_EXCEPTION
195 dvmFprintf(stderr, " show_exception=%d", DVM_SHOW_EXCEPTION);
197 dvmFprintf(stderr, "\n\n");
201 * Show helpful information on JDWP options.
203 static void showJdwpHelp(void)
206 "Example: -Xrunjdwp:transport=dt_socket,address=8000,server=y\n");
208 "Example: -Xrunjdwp:transport=dt_socket,address=localhost:6500,server=n\n");
212 * Show version and copyright info.
214 static void showVersion(void)
216 dvmFprintf(stdout, "DalvikVM version %d.%d.%d\n",
217 DALVIK_MAJOR_VERSION, DALVIK_MINOR_VERSION, DALVIK_BUG_VERSION);
219 "Copyright (C) 2007 The Android Open Source Project\n\n"
220 "This software is built from source code licensed under the "
222 "Version 2.0 (the \"License\"). You may obtain a copy of the "
224 " http://www.apache.org/licenses/LICENSE-2.0\n\n"
225 "See the associated NOTICE file for this software for further "
230 * Parse a string of the form /[0-9]+[kKmMgG]?/, which is used to specify
231 * memory sizes. [kK] indicates kilobytes, [mM] megabytes, and
234 * "s" should point just past the "-Xm?" part of the string.
235 * "min" specifies the lowest acceptable value described by "s".
236 * "div" specifies a divisor, e.g. 1024 if the value must be a multiple
239 * The spec says the -Xmx and -Xms options must be multiples of 1024. It
240 * doesn't say anything about -Xss.
242 * Returns 0 (a useless size) if "s" is malformed or specifies a low or
243 * non-evenly-divisible value.
245 static size_t parseMemOption(const char *s, size_t div)
247 /* strtoul accepts a leading [+-], which we don't want,
248 * so make sure our string starts with a decimal digit.
254 val = strtoul(s, (char **)&s2, 10);
256 /* s2 should be pointing just after the number.
257 * If this is the end of the string, the user
258 * has specified a number of bytes. Otherwise,
259 * there should be exactly one more character
260 * that specifies a multiplier.
265 /* The remainder of the string is either a single multiplier
266 * character, or nothing to indicate that the value is in
275 } else if (c == 'k' || c == 'K') {
277 } else if (c == 'm' || c == 'M') {
279 } else if (c == 'g' || c == 'G') {
280 mul = 1024 * 1024 * 1024;
282 /* Unknown multiplier character.
287 if (val <= SIZE_MAX / mul) {
290 /* Clamp to a multiple of 1024.
292 val = SIZE_MAX & ~(1024-1);
295 /* There's more than one character after the
302 /* The man page says that a -Xm value must be
303 * a multiple of 1024.
305 if (val % div == 0) {
315 * Handle one of the JDWP name/value pairs.
318 * help: if specified, show help message and bail
319 * transport: may be dt_socket or dt_shmem
320 * address: for dt_socket, "host:port", or just "port" when listening
321 * server: if "y", wait for debugger to attach; if "n", attach to debugger
322 * timeout: how long to wait for debugger to connect / listen
324 * Useful with server=n (these aren't supported yet):
325 * onthrow=<exception-name>: connect to debugger when exception thrown
326 * onuncaught=y|n: connect to debugger when uncaught exception thrown
327 * launch=<command-line>: launch the debugger itself
329 * The "transport" option is required, as is "address" if server=n.
331 static bool handleJdwpOption(const char* name, const char* value)
333 if (strcmp(name, "transport") == 0) {
334 if (strcmp(value, "dt_socket") == 0) {
335 gDvm.jdwpTransport = kJdwpTransportSocket;
336 } else if (strcmp(value, "dt_android_adb") == 0) {
337 gDvm.jdwpTransport = kJdwpTransportAndroidAdb;
339 LOGE("JDWP transport '%s' not supported\n", value);
342 } else if (strcmp(name, "server") == 0) {
344 gDvm.jdwpServer = false;
345 else if (*value == 'y')
346 gDvm.jdwpServer = true;
348 LOGE("JDWP option 'server' must be 'y' or 'n'\n");
351 } else if (strcmp(name, "suspend") == 0) {
353 gDvm.jdwpSuspend = false;
354 else if (*value == 'y')
355 gDvm.jdwpSuspend = true;
357 LOGE("JDWP option 'suspend' must be 'y' or 'n'\n");
360 } else if (strcmp(name, "address") == 0) {
361 /* this is either <port> or <host>:<port> */
362 const char* colon = strchr(value, ':');
368 gDvm.jdwpHost = (char*) malloc(colon - value +1);
369 strncpy(gDvm.jdwpHost, value, colon - value +1);
370 gDvm.jdwpHost[colon-value] = '\0';
373 if (*value == '\0') {
374 LOGE("JDWP address missing port\n");
377 port = strtol(value, &end, 10);
379 LOGE("JDWP address has junk in port field '%s'\n", value);
382 gDvm.jdwpPort = port;
383 } else if (strcmp(name, "launch") == 0 ||
384 strcmp(name, "onthrow") == 0 ||
385 strcmp(name, "oncaught") == 0 ||
386 strcmp(name, "timeout") == 0)
388 /* valid but unsupported */
389 LOGI("Ignoring JDWP option '%s'='%s'\n", name, value);
391 LOGI("Ignoring unrecognized JDWP option '%s'='%s'\n", name, value);
398 * Parse the latter half of a -Xrunjdwp/-agentlib:jdwp= string, e.g.:
399 * "transport=dt_socket,address=8000,server=y,suspend=n"
401 static bool parseJdwpOptions(const char* str)
403 char* mangle = strdup(str);
408 * Process all of the name=value pairs.
414 value = strchr(name, '=');
416 LOGE("JDWP opts: garbage at '%s'\n", name);
420 comma = strchr(name, ','); // use name, not value, for safety
423 LOGE("JDWP opts: found comma before '=' in '%s'\n", mangle);
429 *value++ = '\0'; // stomp the '='
431 if (!handleJdwpOption(name, value))
442 * Make sure the combination of arguments makes sense.
444 if (gDvm.jdwpTransport == kJdwpTransportUnknown) {
445 LOGE("JDWP opts: must specify transport\n");
448 if (!gDvm.jdwpServer && (gDvm.jdwpHost == NULL || gDvm.jdwpPort == 0)) {
449 LOGE("JDWP opts: when server=n, must specify host and port\n");
452 // transport mandatory
453 // outbound server address
455 gDvm.jdwpConfigured = true;
464 * Handle one of the four kinds of assertion arguments.
466 * "pkgOrClass" is the last part of an enable/disable line. For a package
467 * the arg looks like "-ea:com.google.fubar...", for a class it looks
468 * like "-ea:com.google.fubar.Wahoo". The string we get starts at the ':'.
470 * For system assertions (-esa/-dsa), "pkgOrClass" is NULL.
472 * Multiple instances of these arguments can be specified, e.g. you can
473 * enable assertions for a package and then disable them for one class in
476 static bool enableAssertions(const char* pkgOrClass, bool enable)
478 AssertionControl* pCtrl = &gDvm.assertionCtrl[gDvm.assertionCtrlCount++];
479 pCtrl->enable = enable;
481 if (pkgOrClass == NULL) {
482 /* enable or disable for all system classes */
483 pCtrl->isPackage = false;
484 pCtrl->pkgOrClass = NULL;
485 pCtrl->pkgOrClassLen = 0;
487 if (*pkgOrClass == '\0') {
488 /* global enable/disable for all but system */
489 pCtrl->isPackage = false;
490 pCtrl->pkgOrClass = strdup("");
491 pCtrl->pkgOrClassLen = 0;
493 pCtrl->pkgOrClass = dvmDotToSlash(pkgOrClass+1); // skip ':'
494 if (pCtrl->pkgOrClass == NULL) {
495 /* can happen if class name includes an illegal '/' */
496 LOGW("Unable to process assertion arg '%s'\n", pkgOrClass);
500 int len = strlen(pCtrl->pkgOrClass);
501 if (len >= 3 && strcmp(pCtrl->pkgOrClass + len-3, "///") == 0) {
502 /* mark as package, truncate two of the three slashes */
503 pCtrl->isPackage = true;
504 *(pCtrl->pkgOrClass + len-2) = '\0';
505 pCtrl->pkgOrClassLen = len - 2;
508 pCtrl->isPackage = false;
509 pCtrl->pkgOrClassLen = len;
518 * Turn assertions on when requested to do so by the Zygote.
520 * This is a bit sketchy. We can't (easily) go back and fiddle with all
521 * of the classes that have already been initialized, so this only
522 * affects classes that have yet to be loaded. If some or all assertions
523 * have been enabled through some other means, we don't want to mess with
524 * it here, so we do nothing. Finally, we assume that there's room in
525 * "assertionCtrl" to hold at least one entry; this is guaranteed by the
528 * This must only be called from the main thread during zygote init.
530 void dvmLateEnableAssertions(void)
532 if (gDvm.assertionCtrl == NULL) {
533 LOGD("Not late-enabling assertions: no assertionCtrl array\n");
535 } else if (gDvm.assertionCtrlCount != 0) {
536 LOGD("Not late-enabling assertions: some asserts already configured\n");
539 LOGD("Late-enabling assertions\n");
541 /* global enable for all but system */
542 AssertionControl* pCtrl = gDvm.assertionCtrl;
543 pCtrl->pkgOrClass = strdup("");
544 pCtrl->pkgOrClassLen = 0;
545 pCtrl->isPackage = false;
546 pCtrl->enable = true;
547 gDvm.assertionCtrlCount = 1;
552 * Release memory associated with the AssertionCtrl array.
554 static void freeAssertionCtrl(void)
558 for (i = 0; i < gDvm.assertionCtrlCount; i++)
559 free(gDvm.assertionCtrl[i].pkgOrClass);
560 free(gDvm.assertionCtrl);
563 #if defined(WITH_JIT)
564 /* Parse -Xjitop to selectively turn on/off certain opcodes for JIT */
565 static void processXjitop(const char *opt)
568 const char *startPtr = &opt[8];
572 long startValue, endValue;
574 startValue = strtol(startPtr, &endPtr, 16);
575 if (startPtr != endPtr) {
576 /* Just in case value is out of range */
579 if (*endPtr == '-') {
580 endValue = strtol(endPtr+1, &endPtr, 16);
583 endValue = startValue;
586 for (; startValue <= endValue; startValue++) {
587 LOGW("Dalvik opcode %x is selected for debugging",
588 (unsigned int) startValue);
589 /* Mark the corresponding bit to 1 */
590 gDvmJit.opList[startValue >> 3] |=
591 1 << (startValue & 0x7);
598 startPtr = endPtr + 1;
604 "Warning: Unrecognized opcode value substring "
612 for (i = 0; i < 32; i++) {
613 gDvmJit.opList[i] = 0xff;
615 dvmFprintf(stderr, "Warning: select all opcodes\n");
619 /* Parse -Xjitmethod to selectively turn on/off certain methods for JIT */
620 static void processXjitmethod(const char *opt)
622 char *buf = strdup(&opt[12]);
625 gDvmJit.methodTable = dvmHashTableCreate(8, NULL);
629 * Break comma-separated method signatures and enter them into the hash
630 * table individually.
635 end = strchr(start, ',');
640 hashValue = dvmComputeUtf8Hash(start);
642 dvmHashTableLookup(gDvmJit.methodTable, hashValue,
644 (HashCompareFunc) strcmp, true);
656 * Process an argument vector full of options. Unlike standard C programs,
657 * argv[0] does not contain the name of the program.
659 * If "ignoreUnrecognized" is set, we ignore options starting with "-X" or "_"
660 * that we don't recognize. Otherwise, we return with an error as soon as
661 * we see anything we can't identify.
663 * Returns 0 on success, -1 on failure, and 1 for the special case of
664 * "-version" where we want to stop without showing an error message.
666 static int processOptions(int argc, const char* const argv[],
667 bool ignoreUnrecognized)
671 LOGV("VM options (%d):\n", argc);
672 for (i = 0; i < argc; i++)
673 LOGV(" %d: '%s'\n", i, argv[i]);
676 * Over-allocate AssertionControl array for convenience. If allocated,
677 * the array must be able to hold at least one entry, so that the
678 * zygote-time activation can do its business.
680 assert(gDvm.assertionCtrl == NULL);
683 (AssertionControl*) malloc(sizeof(AssertionControl) * argc);
684 if (gDvm.assertionCtrl == NULL)
686 assert(gDvm.assertionCtrlCount == 0);
689 for (i = 0; i < argc; i++) {
690 if (strcmp(argv[i], "-help") == 0) {
691 /* show usage and stop */
694 } else if (strcmp(argv[i], "-version") == 0) {
695 /* show version and stop */
698 } else if (strcmp(argv[i], "-showversion") == 0) {
699 /* show version and continue */
702 } else if (strcmp(argv[i], "-classpath") == 0 ||
703 strcmp(argv[i], "-cp") == 0)
707 dvmFprintf(stderr, "Missing classpath path list\n");
710 free(gDvm.classPathStr); /* in case we have compiled-in default */
711 gDvm.classPathStr = strdup(argv[++i]);
713 } else if (strncmp(argv[i], "-Xbootclasspath:",
714 sizeof("-Xbootclasspath:")-1) == 0)
716 /* set bootclasspath */
717 const char* path = argv[i] + sizeof("-Xbootclasspath:")-1;
720 dvmFprintf(stderr, "Missing bootclasspath path list\n");
723 free(gDvm.bootClassPathStr);
724 gDvm.bootClassPathStr = strdup(path);
726 } else if (strncmp(argv[i], "-Xbootclasspath/a:",
727 sizeof("-Xbootclasspath/a:")-1) == 0) {
728 const char* appPath = argv[i] + sizeof("-Xbootclasspath/a:")-1;
730 if (*(appPath) == '\0') {
731 dvmFprintf(stderr, "Missing appending bootclasspath path list\n");
736 if (asprintf(&allPath, "%s:%s", gDvm.bootClassPathStr, appPath) < 0) {
737 dvmFprintf(stderr, "Can't append to bootclasspath path list\n");
740 free(gDvm.bootClassPathStr);
741 gDvm.bootClassPathStr = allPath;
743 } else if (strncmp(argv[i], "-Xbootclasspath/p:",
744 sizeof("-Xbootclasspath/p:")-1) == 0) {
745 const char* prePath = argv[i] + sizeof("-Xbootclasspath/p:")-1;
747 if (*(prePath) == '\0') {
748 dvmFprintf(stderr, "Missing prepending bootclasspath path list\n");
753 if (asprintf(&allPath, "%s:%s", prePath, gDvm.bootClassPathStr) < 0) {
754 dvmFprintf(stderr, "Can't prepend to bootclasspath path list\n");
757 free(gDvm.bootClassPathStr);
758 gDvm.bootClassPathStr = allPath;
760 } else if (strncmp(argv[i], "-D", 2) == 0) {
762 dvmAddCommandLineProperty(argv[i] + 2);
764 } else if (strcmp(argv[i], "-jar") == 0) {
765 // TODO: handle this; name of jar should be in argv[i+1]
766 dvmFprintf(stderr, "-jar not yet handled\n");
769 } else if (strncmp(argv[i], "-Xms", 4) == 0) {
770 size_t val = parseMemOption(argv[i]+4, 1024);
772 if (val >= kMinHeapStartSize && val <= kMaxHeapSize) {
773 gDvm.heapStartingSize = val;
776 "Invalid -Xms '%s', range is %dKB to %dKB\n",
777 argv[i], kMinHeapStartSize/1024, kMaxHeapSize/1024);
781 dvmFprintf(stderr, "Invalid -Xms option '%s'\n", argv[i]);
784 } else if (strncmp(argv[i], "-Xmx", 4) == 0) {
785 size_t val = parseMemOption(argv[i]+4, 1024);
787 if (val >= kMinHeapSize && val <= kMaxHeapSize) {
788 gDvm.heapMaximumSize = val;
791 "Invalid -Xmx '%s', range is %dKB to %dKB\n",
792 argv[i], kMinHeapSize/1024, kMaxHeapSize/1024);
796 dvmFprintf(stderr, "Invalid -Xmx option '%s'\n", argv[i]);
799 } else if (strncmp(argv[i], "-XX:HeapGrowthLimit=", 20) == 0) {
800 size_t val = parseMemOption(argv[i] + 20, 1024);
802 gDvm.heapGrowthLimit = val;
804 dvmFprintf(stderr, "Invalid -XX:HeapGrowthLimit option '%s'\n", argv[i]);
807 } else if (strncmp(argv[i], "-Xss", 4) == 0) {
808 size_t val = parseMemOption(argv[i]+4, 1);
810 if (val >= kMinStackSize && val <= kMaxStackSize) {
811 gDvm.stackSize = val;
813 dvmFprintf(stderr, "Invalid -Xss '%s', range is %d to %d\n",
814 argv[i], kMinStackSize, kMaxStackSize);
818 dvmFprintf(stderr, "Invalid -Xss option '%s'\n", argv[i]);
822 } else if (strncmp(argv[i], "-XX:+DisableExplicitGC", 22) == 0) {
823 gDvm.disableExplicitGc = true;
824 } else if (strcmp(argv[i], "-verbose") == 0 ||
825 strcmp(argv[i], "-verbose:class") == 0)
827 // JNI spec says "-verbose:gc,class" is valid, but cmd line
828 // doesn't work that way; may want to support.
829 gDvm.verboseClass = true;
830 } else if (strcmp(argv[i], "-verbose:jni") == 0) {
831 gDvm.verboseJni = true;
832 } else if (strcmp(argv[i], "-verbose:gc") == 0) {
833 gDvm.verboseGc = true;
834 } else if (strcmp(argv[i], "-verbose:shutdown") == 0) {
835 gDvm.verboseShutdown = true;
837 } else if (strncmp(argv[i], "-enableassertions", 17) == 0) {
838 enableAssertions(argv[i] + 17, true);
839 } else if (strncmp(argv[i], "-ea", 3) == 0) {
840 enableAssertions(argv[i] + 3, true);
841 } else if (strncmp(argv[i], "-disableassertions", 18) == 0) {
842 enableAssertions(argv[i] + 18, false);
843 } else if (strncmp(argv[i], "-da", 3) == 0) {
844 enableAssertions(argv[i] + 3, false);
845 } else if (strcmp(argv[i], "-enablesystemassertions") == 0 ||
846 strcmp(argv[i], "-esa") == 0)
848 enableAssertions(NULL, true);
849 } else if (strcmp(argv[i], "-disablesystemassertions") == 0 ||
850 strcmp(argv[i], "-dsa") == 0)
852 enableAssertions(NULL, false);
854 } else if (strncmp(argv[i], "-Xcheck:jni", 11) == 0) {
855 /* nothing to do now -- was handled during JNI init */
857 } else if (strcmp(argv[i], "-Xdebug") == 0) {
858 /* accept but ignore */
860 } else if (strncmp(argv[i], "-Xrunjdwp:", 10) == 0 ||
861 strncmp(argv[i], "-agentlib:jdwp=", 15) == 0)
865 if (argv[i][1] == 'X')
870 if (strncmp(tail, "help", 4) == 0 || !parseJdwpOptions(tail)) {
874 } else if (strcmp(argv[i], "-Xrs") == 0) {
875 gDvm.reduceSignals = true;
876 } else if (strcmp(argv[i], "-Xnoquithandler") == 0) {
877 /* disables SIGQUIT handler thread while still blocking SIGQUIT */
878 /* (useful if we don't want thread but system still signals us) */
879 gDvm.noQuitHandler = true;
880 } else if (strcmp(argv[i], "-Xzygote") == 0) {
882 #if defined(WITH_JIT)
883 gDvmJit.runningInAndroidFramework = true;
885 } else if (strncmp(argv[i], "-Xdexopt:", 9) == 0) {
886 if (strcmp(argv[i] + 9, "none") == 0)
887 gDvm.dexOptMode = OPTIMIZE_MODE_NONE;
888 else if (strcmp(argv[i] + 9, "verified") == 0)
889 gDvm.dexOptMode = OPTIMIZE_MODE_VERIFIED;
890 else if (strcmp(argv[i] + 9, "all") == 0)
891 gDvm.dexOptMode = OPTIMIZE_MODE_ALL;
893 dvmFprintf(stderr, "Unrecognized dexopt option '%s'\n",argv[i]);
896 } else if (strncmp(argv[i], "-Xverify:", 9) == 0) {
897 if (strcmp(argv[i] + 9, "none") == 0)
898 gDvm.classVerifyMode = VERIFY_MODE_NONE;
899 else if (strcmp(argv[i] + 9, "remote") == 0)
900 gDvm.classVerifyMode = VERIFY_MODE_REMOTE;
901 else if (strcmp(argv[i] + 9, "all") == 0)
902 gDvm.classVerifyMode = VERIFY_MODE_ALL;
904 dvmFprintf(stderr, "Unrecognized verify option '%s'\n",argv[i]);
907 } else if (strncmp(argv[i], "-Xjnigreflimit:", 15) == 0) {
908 int lim = atoi(argv[i] + 15);
909 if (lim < 200 || (lim % 100) != 0) {
910 dvmFprintf(stderr, "Bad value for -Xjnigreflimit: '%s'\n",
914 gDvm.jniGrefLimit = lim;
915 } else if (strncmp(argv[i], "-Xjnitrace:", 11) == 0) {
916 gDvm.jniTrace = strdup(argv[i] + 11);
917 } else if (strcmp(argv[i], "-Xlog-stdio") == 0) {
918 gDvm.logStdio = true;
920 } else if (strncmp(argv[i], "-Xint", 5) == 0) {
921 if (argv[i][5] == ':') {
922 if (strcmp(argv[i] + 6, "portable") == 0)
923 gDvm.executionMode = kExecutionModeInterpPortable;
924 else if (strcmp(argv[i] + 6, "fast") == 0)
925 gDvm.executionMode = kExecutionModeInterpFast;
927 else if (strcmp(argv[i] + 6, "jit") == 0)
928 gDvm.executionMode = kExecutionModeJit;
932 "Warning: Unrecognized interpreter mode %s\n",argv[i]);
936 /* disable JIT if it was enabled by default */
937 gDvm.executionMode = kExecutionModeInterpFast;
940 } else if (strncmp(argv[i], "-Xlockprofthreshold:", 20) == 0) {
941 gDvm.lockProfThreshold = atoi(argv[i] + 20);
944 } else if (strncmp(argv[i], "-Xjitop", 7) == 0) {
945 processXjitop(argv[i]);
946 } else if (strncmp(argv[i], "-Xjitmethod", 11) == 0) {
947 processXjitmethod(argv[i]);
948 } else if (strncmp(argv[i], "-Xjitblocking", 13) == 0) {
949 gDvmJit.blockingMode = true;
950 } else if (strncmp(argv[i], "-Xjitthreshold:", 15) == 0) {
951 gDvmJit.threshold = atoi(argv[i] + 15);
952 } else if (strncmp(argv[i], "-Xincludeselectedop", 19) == 0) {
953 gDvmJit.includeSelectedOp = true;
954 } else if (strncmp(argv[i], "-Xincludeselectedmethod", 23) == 0) {
955 gDvmJit.includeSelectedMethod = true;
956 } else if (strncmp(argv[i], "-Xjitcheckcg", 12) == 0) {
957 gDvmJit.checkCallGraph = true;
958 /* Need to enable blocking mode due to stack crawling */
959 gDvmJit.blockingMode = true;
960 } else if (strncmp(argv[i], "-Xjitverbose", 12) == 0) {
961 gDvmJit.printMe = true;
962 } else if (strncmp(argv[i], "-Xjitprofile", 12) == 0) {
963 gDvmJit.profile = true;
964 } else if (strncmp(argv[i], "-Xjitdisableopt", 15) == 0) {
965 /* Disable selected optimizations */
966 if (argv[i][15] == ':') {
967 sscanf(argv[i] + 16, "%x", &gDvmJit.disableOpt);
968 /* Disable all optimizations */
970 gDvmJit.disableOpt = -1;
974 } else if (strncmp(argv[i], "-Xdeadlockpredict:", 18) == 0) {
975 #ifdef WITH_DEADLOCK_PREDICTION
976 if (strcmp(argv[i] + 18, "off") == 0)
977 gDvm.deadlockPredictMode = kDPOff;
978 else if (strcmp(argv[i] + 18, "warn") == 0)
979 gDvm.deadlockPredictMode = kDPWarn;
980 else if (strcmp(argv[i] + 18, "err") == 0)
981 gDvm.deadlockPredictMode = kDPErr;
982 else if (strcmp(argv[i] + 18, "abort") == 0)
983 gDvm.deadlockPredictMode = kDPAbort;
985 dvmFprintf(stderr, "Bad value for -Xdeadlockpredict");
988 if (gDvm.deadlockPredictMode != kDPOff)
989 LOGD("Deadlock prediction enabled (%s)\n", argv[i]+18);
992 } else if (strncmp(argv[i], "-Xstacktracefile:", 17) == 0) {
993 gDvm.stackTraceFile = strdup(argv[i]+17);
995 } else if (strcmp(argv[i], "-Xgenregmap") == 0) {
996 gDvm.generateRegisterMaps = true;
997 LOGV("Register maps will be generated during verification\n");
999 } else if (strcmp(argv[i], "Xverifyopt:checkmon") == 0) {
1000 gDvm.monitorVerification = true;
1001 } else if (strcmp(argv[i], "Xverifyopt:nocheckmon") == 0) {
1002 gDvm.monitorVerification = false;
1004 } else if (strncmp(argv[i], "-Xgc:", 5) == 0) {
1005 if (strcmp(argv[i] + 5, "precise") == 0)
1006 gDvm.preciseGc = true;
1007 else if (strcmp(argv[i] + 5, "noprecise") == 0)
1008 gDvm.preciseGc = false;
1009 else if (strcmp(argv[i] + 5, "preverify") == 0)
1010 gDvm.preVerify = true;
1011 else if (strcmp(argv[i] + 5, "nopreverify") == 0)
1012 gDvm.preVerify = false;
1013 else if (strcmp(argv[i] + 5, "postverify") == 0)
1014 gDvm.postVerify = true;
1015 else if (strcmp(argv[i] + 5, "nopostverify") == 0)
1016 gDvm.postVerify = false;
1017 else if (strcmp(argv[i] + 5, "concurrent") == 0)
1018 gDvm.concurrentMarkSweep = true;
1019 else if (strcmp(argv[i] + 5, "noconcurrent") == 0)
1020 gDvm.concurrentMarkSweep = false;
1021 else if (strcmp(argv[i] + 5, "verifycardtable") == 0)
1022 gDvm.verifyCardTable = true;
1023 else if (strcmp(argv[i] + 5, "noverifycardtable") == 0)
1024 gDvm.verifyCardTable = false;
1026 dvmFprintf(stderr, "Bad value for -Xgc");
1029 LOGV("Precise GC configured %s\n", gDvm.preciseGc ? "ON" : "OFF");
1031 } else if (strcmp(argv[i], "-Xcheckdexsum") == 0) {
1032 gDvm.verifyDexChecksum = true;
1034 } else if (strcmp(argv[i], "-Xprofile:wallclock") == 0) {
1035 gDvm.profilerWallClock = true;
1038 if (!ignoreUnrecognized) {
1039 dvmFprintf(stderr, "Unrecognized option '%s'\n", argv[i]);
1049 * Set defaults for fields altered or modified by arguments.
1051 * Globals are initialized to 0 (a/k/a NULL or false).
1053 static void setCommandLineDefaults()
1057 envStr = getenv("CLASSPATH");
1059 gDvm.classPathStr = strdup(envStr);
1061 gDvm.classPathStr = strdup(".");
1062 envStr = getenv("BOOTCLASSPATH");
1064 gDvm.bootClassPathStr = strdup(envStr);
1066 gDvm.bootClassPathStr = strdup(".");
1068 /* Defaults overridden by -Xms and -Xmx.
1069 * TODO: base these on a system or application-specific default
1071 gDvm.heapStartingSize = 2 * 1024 * 1024; // Spec says 16MB; too big for us.
1072 gDvm.heapMaximumSize = 16 * 1024 * 1024; // Spec says 75% physical mem
1073 gDvm.heapGrowthLimit = 0; // 0 means no growth limit
1074 gDvm.stackSize = kDefaultStackSize;
1076 gDvm.concurrentMarkSweep = true;
1078 /* gDvm.jdwpSuspend = true; */
1080 /* allowed unless zygote config doesn't allow it */
1081 gDvm.jdwpAllowed = true;
1083 /* default verification and optimization modes */
1084 gDvm.classVerifyMode = VERIFY_MODE_ALL;
1085 gDvm.dexOptMode = OPTIMIZE_MODE_VERIFIED;
1086 gDvm.monitorVerification = false;
1089 * Default execution mode.
1091 * This should probably interact with the mterp code somehow, e.g. if
1092 * we know we're using the "desktop" build we should probably be
1093 * using "portable" rather than "fast".
1095 #if defined(WITH_JIT)
1096 gDvm.executionMode = kExecutionModeJit;
1098 gDvm.executionMode = kExecutionModeInterpFast;
1102 * SMP support is a compile-time define, but we may want to have
1103 * dexopt target a differently-configured device.
1105 gDvm.dexOptForSmp = (ANDROID_SMP != 0);
1110 * Handle a SIGBUS, which frequently occurs because somebody replaced an
1111 * optimized DEX file out from under us.
1113 static void busCatcher(int signum, siginfo_t* info, void* context)
1115 void* addr = info->si_addr;
1117 LOGE("Caught a SIGBUS (%d), addr=%p\n", signum, addr);
1120 * If we return at this point the SIGBUS just keeps happening, so we
1121 * remove the signal handler and allow it to kill us. TODO: restore
1122 * the original, which points to a debuggerd stub; if we don't then
1123 * debuggerd won't be notified.
1125 signal(SIGBUS, SIG_DFL);
1129 * Configure signals. We need to block SIGQUIT so that the signal only
1130 * reaches the dump-stack-trace thread.
1132 * This can be disabled with the "-Xrs" flag.
1134 static void blockSignals()
1140 sigaddset(&mask, SIGQUIT);
1141 sigaddset(&mask, SIGUSR1); // used to initiate heap dump
1142 #if defined(WITH_JIT) && defined(WITH_JIT_TUNING)
1143 sigaddset(&mask, SIGUSR2); // used to investigate JIT internals
1145 //sigaddset(&mask, SIGPIPE);
1146 cc = sigprocmask(SIG_BLOCK, &mask, NULL);
1150 /* TODO: save the old sigaction in a global */
1151 struct sigaction sa;
1152 memset(&sa, 0, sizeof(sa));
1153 sa.sa_sigaction = busCatcher;
1154 sa.sa_flags = SA_SIGINFO;
1155 cc = sigaction(SIGBUS, &sa, NULL);
1161 * VM initialization. Pass in any options provided on the command line.
1162 * Do not pass in the class name or the options for the class.
1164 * Returns 0 on success.
1166 int dvmStartup(int argc, const char* const argv[], bool ignoreUnrecognized,
1171 assert(gDvm.initializing);
1173 LOGV("VM init args (%d):\n", argc);
1174 for (i = 0; i < argc; i++)
1175 LOGV(" %d: '%s'\n", i, argv[i]);
1177 setCommandLineDefaults();
1179 /* prep properties storage */
1180 if (!dvmPropertiesStartup(argc))
1184 * Process the option flags (if any).
1186 cc = processOptions(argc, argv, ignoreUnrecognized);
1189 dvmFprintf(stderr, "\n");
1195 #if WITH_EXTRA_GC_CHECKS > 1
1196 /* only "portable" interp has the extra goodies */
1197 if (gDvm.executionMode != kExecutionModeInterpPortable) {
1198 LOGI("Switching to 'portable' interpreter for GC checks\n");
1199 gDvm.executionMode = kExecutionModeInterpPortable;
1203 /* Configure group scheduling capabilities */
1204 if (!access("/dev/cpuctl/tasks", F_OK)) {
1205 LOGV("Using kernel group scheduling");
1206 gDvm.kernelGroupScheduling = 1;
1208 LOGV("Using kernel scheduler policies");
1211 /* configure signal handling */
1212 if (!gDvm.reduceSignals)
1215 /* verify system page size */
1216 if (sysconf(_SC_PAGESIZE) != SYSTEM_PAGE_SIZE) {
1217 LOGE("ERROR: expected page size %d, got %d\n",
1218 SYSTEM_PAGE_SIZE, (int) sysconf(_SC_PAGESIZE));
1223 LOGV("Using executionMode %d\n", gDvm.executionMode);
1224 dvmCheckAsmConstants();
1227 * Initialize components.
1229 if (!dvmAllocTrackerStartup())
1231 if (!dvmGcStartup())
1233 if (!dvmThreadStartup())
1235 if (!dvmInlineNativeStartup())
1237 if (!dvmRegisterMapStartup())
1239 if (!dvmInstanceofStartup())
1241 if (!dvmClassStartup())
1243 if (!dvmBaseClassStartup())
1245 if (!dvmThreadObjStartup())
1247 if (!dvmExceptionStartup())
1249 if (!dvmStringInternStartup())
1251 if (!dvmNativeStartup())
1253 if (!dvmInternalNativeStartup())
1255 if (!dvmJniStartup())
1257 if (!dvmReflectStartup())
1259 if (!dvmProfilingStartup())
1262 /* make sure we got these [can this go away?] */
1263 assert(gDvm.classJavaLangClass != NULL);
1264 assert(gDvm.classJavaLangObject != NULL);
1265 //assert(gDvm.classJavaLangString != NULL);
1266 assert(gDvm.classJavaLangThread != NULL);
1267 assert(gDvm.classJavaLangVMThread != NULL);
1268 assert(gDvm.classJavaLangThreadGroup != NULL);
1271 * Make sure these exist. If they don't, we can return a failure out
1272 * of main and nip the whole thing in the bud.
1274 static const char* earlyClasses[] = {
1275 "Ljava/lang/InternalError;",
1276 "Ljava/lang/StackOverflowError;",
1277 "Ljava/lang/UnsatisfiedLinkError;",
1278 "Ljava/lang/NoClassDefFoundError;",
1281 const char** pClassName;
1282 for (pClassName = earlyClasses; *pClassName != NULL; pClassName++) {
1283 if (dvmFindSystemClassNoInit(*pClassName) == NULL)
1288 * Miscellaneous class library validation.
1290 if (!dvmValidateBoxClasses())
1294 * Do the last bits of Thread struct initialization we need to allow
1295 * JNI calls to work.
1297 if (!dvmPrepMainForJni(pEnv))
1301 * Explicitly initialize java.lang.Class. This doesn't happen
1302 * automatically because it's allocated specially (it's an instance
1303 * of itself). Must happen before registration of system natives,
1304 * which make some calls that throw assertions if the classes they
1305 * operate on aren't initialized.
1307 if (!dvmInitClass(gDvm.classJavaLangClass))
1311 * Register the system native methods, which are registered through JNI.
1313 if (!registerSystemNatives(pEnv))
1317 * Do some "late" initialization for the memory allocator. This may
1318 * allocate storage and initialize classes.
1320 if (!dvmCreateStockExceptions())
1324 * At this point, the VM is in a pretty good state. Finish prep on
1325 * the main thread (specifically, create a java.lang.Thread object to go
1326 * along with our Thread struct). Note we will probably be executing
1327 * some interpreted class initializer code in here.
1329 if (!dvmPrepMainThread())
1333 * Make sure we haven't accumulated any tracked references. The main
1334 * thread should be starting with a clean slate.
1336 if (dvmReferenceTableEntries(&dvmThreadSelf()->internalLocalRefTable) != 0)
1338 LOGW("Warning: tracked references remain post-initialization\n");
1339 dvmDumpReferenceTable(&dvmThreadSelf()->internalLocalRefTable, "MAIN");
1342 /* general debugging setup */
1343 if (!dvmDebuggerStartup())
1346 if (!dvmInlineNativeCheck())
1350 * Init for either zygote mode or non-zygote mode. The key difference
1351 * is that we don't start any additional threads in Zygote mode.
1357 if (!dvmInitAfterZygote())
1364 LOGE("dmvTestHash FAILED\n");
1365 if (false /*noisy!*/ && !dvmTestIndirectRefTable())
1366 LOGE("dvmTestIndirectRefTable FAILED\n");
1369 assert(!dvmCheckException(dvmThreadSelf()));
1370 gDvm.initExceptionCount = 0;
1380 * Register java.* natives from our class libraries. We need to do
1381 * this after we're ready for JNI registration calls, but before we
1382 * do any class initialization.
1384 * If we get this wrong, we will blow up in the ThreadGroup class init if
1385 * interpreted code makes any reference to System. It will likely do this
1386 * since it wants to do some java.io.File setup (e.g. for static in/out/err).
1388 * We need to have gDvm.initializing raised here so that JNI FindClass
1389 * won't try to use the system/application class loader.
1391 static bool registerSystemNatives(JNIEnv* pEnv)
1395 /* main thread is always first in list */
1396 self = gDvm.threadList;
1398 /* must set this before allowing JNI-based method registration */
1399 self->status = THREAD_NATIVE;
1401 if (jniRegisterSystemMethods(pEnv) < 0) {
1402 LOGE("jniRegisterSystemMethods failed");
1406 /* back to run mode */
1407 self->status = THREAD_RUNNING;
1414 * Do zygote-mode-only initialization.
1416 static bool initZygote(void)
1418 /* zygote goes into its own process group */
1425 * Do non-zygote-mode initialization. This is done during VM init for
1426 * standard startup, or after a "zygote fork" when creating a new process.
1428 bool dvmInitAfterZygote(void)
1430 u8 startHeap, startQuit, startJdwp;
1431 u8 endHeap, endQuit, endJdwp;
1433 startHeap = dvmGetRelativeTimeUsec();
1436 * Post-zygote heap initialization, including starting
1437 * the HeapWorker thread.
1439 if (!dvmGcStartupAfterZygote())
1442 endHeap = dvmGetRelativeTimeUsec();
1443 startQuit = dvmGetRelativeTimeUsec();
1445 /* start signal catcher thread that dumps stacks on SIGQUIT */
1446 if (!gDvm.reduceSignals && !gDvm.noQuitHandler) {
1447 if (!dvmSignalCatcherStartup())
1451 /* start stdout/stderr copier, if requested */
1452 if (gDvm.logStdio) {
1453 if (!dvmStdioConverterStartup())
1457 endQuit = dvmGetRelativeTimeUsec();
1458 startJdwp = dvmGetRelativeTimeUsec();
1461 * Start JDWP thread. If the command-line debugger flags specified
1462 * "suspend=y", this will pause the VM. We probably want this to
1466 LOGD("JDWP init failed; continuing anyway\n");
1469 endJdwp = dvmGetRelativeTimeUsec();
1471 LOGV("thread-start heap=%d quit=%d jdwp=%d total=%d usec\n",
1472 (int)(endHeap-startHeap), (int)(endQuit-startQuit),
1473 (int)(endJdwp-startJdwp), (int)(endJdwp-startHeap));
1476 if (gDvm.executionMode == kExecutionModeJit) {
1477 if (!dvmCompilerStartup())
1486 * Prepare for a connection to a JDWP-compliant debugger.
1488 * Note this needs to happen fairly late in the startup process, because
1489 * we need to have all of the java.* native methods registered (which in
1490 * turn requires JNI to be fully prepped).
1492 * There are several ways to initialize:
1494 * We immediately try to connect to host:port. Bail on failure. On
1495 * success, send VM_START (suspending the VM if "suspend=y").
1496 * server=y suspend=n
1497 * Passively listen for a debugger to connect. Return immediately.
1498 * server=y suspend=y
1499 * Wait until debugger connects. Send VM_START ASAP, suspending the
1500 * VM after the message is sent.
1502 * This gets more complicated with a nonzero value for "timeout".
1504 static bool initJdwp(void)
1506 assert(!gDvm.zygote);
1509 * Init JDWP if the debugger is enabled. This may connect out to a
1510 * debugger, passively listen for a debugger, or block waiting for a
1513 if (gDvm.jdwpAllowed && gDvm.jdwpConfigured) {
1514 JdwpStartupParams params;
1516 if (gDvm.jdwpHost != NULL) {
1517 if (strlen(gDvm.jdwpHost) >= sizeof(params.host)-1) {
1518 LOGE("ERROR: hostname too long: '%s'\n", gDvm.jdwpHost);
1521 strcpy(params.host, gDvm.jdwpHost);
1523 params.host[0] = '\0';
1525 params.transport = gDvm.jdwpTransport;
1526 params.server = gDvm.jdwpServer;
1527 params.suspend = gDvm.jdwpSuspend;
1528 params.port = gDvm.jdwpPort;
1530 gDvm.jdwpState = dvmJdwpStartup(¶ms);
1531 if (gDvm.jdwpState == NULL) {
1532 LOGW("WARNING: debugger thread failed to initialize\n");
1533 /* TODO: ignore? fail? need to mimic "expected" behavior */
1538 * If a debugger has already attached, send the "welcome" message. This
1539 * may cause us to suspend all threads.
1541 if (dvmJdwpIsActive(gDvm.jdwpState)) {
1542 //dvmChangeStatus(NULL, THREAD_RUNNING);
1543 if (!dvmJdwpPostVMStart(gDvm.jdwpState, gDvm.jdwpSuspend)) {
1544 LOGW("WARNING: failed to post 'start' message to debugger\n");
1547 //dvmChangeStatus(NULL, THREAD_NATIVE);
1554 * An alternative to JNI_CreateJavaVM/dvmStartup that does the first bit
1555 * of initialization and then returns with "initializing" still set. (Used
1556 * by DexOpt command-line utility.)
1558 * Attempting to use JNI or internal natives will fail. It's best
1559 * if no bytecode gets executed, which means no <clinit>, which means
1560 * no exception-throwing. (In practice we need to initialize Class and
1561 * Object, and probably some exception classes.)
1563 * Returns 0 on success.
1565 int dvmPrepForDexOpt(const char* bootClassPath, DexOptimizerMode dexOptMode,
1566 DexClassVerifyMode verifyMode, int dexoptFlags)
1568 gDvm.initializing = true;
1569 gDvm.optimizing = true;
1571 /* configure signal handling */
1574 /* set some defaults */
1575 setCommandLineDefaults();
1576 free(gDvm.bootClassPathStr);
1577 gDvm.bootClassPathStr = strdup(bootClassPath);
1579 /* set opt/verify modes */
1580 gDvm.dexOptMode = dexOptMode;
1581 gDvm.classVerifyMode = verifyMode;
1582 gDvm.generateRegisterMaps = (dexoptFlags & DEXOPT_GEN_REGISTER_MAPS) != 0;
1583 if (dexoptFlags & DEXOPT_SMP) {
1584 assert((dexoptFlags & DEXOPT_UNIPROCESSOR) == 0);
1585 gDvm.dexOptForSmp = true;
1586 } else if (dexoptFlags & DEXOPT_UNIPROCESSOR) {
1587 gDvm.dexOptForSmp = false;
1589 gDvm.dexOptForSmp = (ANDROID_SMP != 0);
1593 * Initialize the heap, some basic thread control mutexes, and
1594 * get the bootclasspath prepped.
1596 * We can't load any classes yet because we may not yet have a source
1597 * for things like java.lang.Object and java.lang.Class.
1599 if (!dvmGcStartup())
1601 if (!dvmThreadStartup())
1603 if (!dvmInlineNativeStartup())
1605 if (!dvmRegisterMapStartup())
1607 if (!dvmInstanceofStartup())
1609 if (!dvmClassStartup())
1613 * We leave gDvm.initializing set to "true" so that, if we're not
1614 * able to process the "core" classes, we don't go into a death-spin
1615 * trying to throw a "class not found" exception.
1627 * All threads have stopped. Finish the shutdown procedure.
1629 * We can also be called if startup fails partway through, so be prepared
1630 * to deal with partially initialized data.
1632 * Free any storage allocated in gGlobals.
1634 * We can't dlclose() shared libs we've loaded, because it's possible a
1635 * thread not associated with the VM is running code in one.
1637 * This is called from the JNI DestroyJavaVM function, which can be
1638 * called from any thread. (In practice, this will usually run in the
1639 * same thread that started the VM, a/k/a the main thread, but we don't
1640 * want to assume that.)
1642 void dvmShutdown(void)
1644 LOGV("VM shutting down\n");
1646 if (CALC_CACHE_STATS)
1647 dvmDumpAtomicCacheStats(gDvm.instanceofCache);
1650 * Stop our internal threads.
1652 dvmGcThreadShutdown();
1654 if (gDvm.jdwpState != NULL)
1655 dvmJdwpShutdown(gDvm.jdwpState);
1656 free(gDvm.jdwpHost);
1657 gDvm.jdwpHost = NULL;
1658 free(gDvm.jniTrace);
1659 gDvm.jniTrace = NULL;
1660 free(gDvm.stackTraceFile);
1661 gDvm.stackTraceFile = NULL;
1663 /* tell signal catcher to shut down if it was started */
1664 dvmSignalCatcherShutdown();
1666 /* shut down stdout/stderr conversion */
1667 dvmStdioConverterShutdown();
1670 if (gDvm.executionMode == kExecutionModeJit) {
1671 /* shut down the compiler thread */
1672 dvmCompilerShutdown();
1677 * Kill any daemon threads that still exist. Actively-running threads
1678 * are likely to crash the process if they continue to execute while
1679 * the VM shuts down.
1683 if (gDvm.verboseShutdown)
1684 LOGD("VM cleaning up\n");
1686 dvmDebuggerShutdown();
1687 dvmReflectShutdown();
1688 dvmProfilingShutdown();
1690 dvmStringInternShutdown();
1691 dvmExceptionShutdown();
1692 dvmThreadShutdown();
1694 dvmRegisterMapShutdown();
1695 dvmInstanceofShutdown();
1696 dvmInlineNativeShutdown();
1698 dvmAllocTrackerShutdown();
1699 dvmPropertiesShutdown();
1701 /* these must happen AFTER dvmClassShutdown has walked through class data */
1702 dvmNativeShutdown();
1703 dvmInternalNativeShutdown();
1705 free(gDvm.bootClassPathStr);
1706 free(gDvm.classPathStr);
1708 freeAssertionCtrl();
1711 * We want valgrind to report anything we forget to free as "definitely
1712 * lost". If there's a pointer in the global chunk, it would be reported
1713 * as "still reachable". Erasing the memory fixes this.
1715 * This must be erased to zero if we want to restart the VM within this
1718 memset(&gDvm, 0xcd, sizeof(gDvm));
1723 * fprintf() wrapper that calls through the JNI-specified vfprintf hook if
1724 * one was specified.
1726 int dvmFprintf(FILE* fp, const char* format, ...)
1731 va_start(args, format);
1732 if (gDvm.vfprintfHook != NULL)
1733 result = (*gDvm.vfprintfHook)(fp, format, args);
1735 result = vfprintf(fp, format, args);
1742 * Abort the VM. We get here on fatal errors. Try very hard not to use
1743 * this; whenever possible, return an error to somebody responsible.
1747 LOGE("VM aborting\n");
1749 fflush(NULL); // flush all open file buffers
1751 /* JNI-supplied abort hook gets right of first refusal */
1752 if (gDvm.abortHook != NULL)
1753 (*gDvm.abortHook)();
1756 * If we call abort(), all threads in the process receives a SIBABRT.
1757 * debuggerd dumps the stack trace of the main thread, whether or not
1758 * that was the thread that failed.
1760 * By stuffing a value into a bogus address, we cause a segmentation
1761 * fault in the current thread, and get a useful log from debuggerd.
1762 * We can also trivially tell the difference between a VM crash and
1763 * a deliberate abort by looking at the fault address.
1765 *((char*)0xdeadd00d) = 38;