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, " -Xgenregmap\n");
123 dvmFprintf(stderr, " -Xverifyopt:[no]checkmon\n");
124 dvmFprintf(stderr, " -Xcheckdexsum\n");
125 #if defined(WITH_JIT)
126 dvmFprintf(stderr, " -Xincludeselectedop\n");
127 dvmFprintf(stderr, " -Xjitop:hexopvalue[-endvalue]"
128 "[,hexopvalue[-endvalue]]*\n");
129 dvmFprintf(stderr, " -Xincludeselectedmethod\n");
130 dvmFprintf(stderr, " -Xjitthreshold:decimalvalue\n");
131 dvmFprintf(stderr, " -Xjitblocking\n");
132 dvmFprintf(stderr, " -Xjitmethod:signature[,signature]* "
133 "(eg Ljava/lang/String\\;replace)\n");
134 dvmFprintf(stderr, " -Xjitcheckcg\n");
135 dvmFprintf(stderr, " -Xjitverbose\n");
136 dvmFprintf(stderr, " -Xjitprofile\n");
137 dvmFprintf(stderr, " -Xjitdisableopt\n");
139 dvmFprintf(stderr, "\n");
140 dvmFprintf(stderr, "Configured with:"
144 #ifdef WITH_HPROF_STACK
147 #ifdef WITH_MONITOR_TRACKING
150 #ifdef WITH_DEADLOCK_PREDICTION
151 " deadlock_prediction"
153 #ifdef WITH_TRACKREF_CHECKS
156 #ifdef WITH_INSTR_CHECKS
159 #ifdef WITH_EXTRA_OBJECT_VALIDATION
160 " extra_object_validation"
162 #ifdef WITH_EXTRA_GC_CHECKS
165 #if !defined(NDEBUG) && defined(WITH_DALVIK_ASSERT)
168 #ifdef WITH_JNI_STACK_CHECK
177 #ifdef PROFILE_FIELD_ACCESS
178 " profile_field_access"
180 #if defined(WITH_JIT)
181 " jit(" ARCH_VARIANT ")"
183 #if defined(WITH_SELF_VERIFICATION)
189 #ifdef WITH_INLINE_PROFILING
193 #ifdef DVM_SHOW_EXCEPTION
194 dvmFprintf(stderr, " show_exception=%d", DVM_SHOW_EXCEPTION);
196 dvmFprintf(stderr, "\n\n");
200 * Show helpful information on JDWP options.
202 static void showJdwpHelp(void)
205 "Example: -Xrunjdwp:transport=dt_socket,address=8000,server=y\n");
207 "Example: -Xrunjdwp:transport=dt_socket,address=localhost:6500,server=n\n");
211 * Show version and copyright info.
213 static void showVersion(void)
215 dvmFprintf(stdout, "DalvikVM version %d.%d.%d\n",
216 DALVIK_MAJOR_VERSION, DALVIK_MINOR_VERSION, DALVIK_BUG_VERSION);
218 "Copyright (C) 2007 The Android Open Source Project\n\n"
219 "This software is built from source code licensed under the "
221 "Version 2.0 (the \"License\"). You may obtain a copy of the "
223 " http://www.apache.org/licenses/LICENSE-2.0\n\n"
224 "See the associated NOTICE file for this software for further "
229 * Parse a string of the form /[0-9]+[kKmMgG]?/, which is used to specify
230 * memory sizes. [kK] indicates kilobytes, [mM] megabytes, and
233 * "s" should point just past the "-Xm?" part of the string.
234 * "min" specifies the lowest acceptable value described by "s".
235 * "div" specifies a divisor, e.g. 1024 if the value must be a multiple
238 * The spec says the -Xmx and -Xms options must be multiples of 1024. It
239 * doesn't say anything about -Xss.
241 * Returns 0 (a useless size) if "s" is malformed or specifies a low or
242 * non-evenly-divisible value.
244 static size_t parseMemOption(const char *s, size_t div)
246 /* strtoul accepts a leading [+-], which we don't want,
247 * so make sure our string starts with a decimal digit.
253 val = strtoul(s, (char **)&s2, 10);
255 /* s2 should be pointing just after the number.
256 * If this is the end of the string, the user
257 * has specified a number of bytes. Otherwise,
258 * there should be exactly one more character
259 * that specifies a multiplier.
264 /* The remainder of the string is either a single multiplier
265 * character, or nothing to indicate that the value is in
274 } else if (c == 'k' || c == 'K') {
276 } else if (c == 'm' || c == 'M') {
278 } else if (c == 'g' || c == 'G') {
279 mul = 1024 * 1024 * 1024;
281 /* Unknown multiplier character.
286 if (val <= SIZE_MAX / mul) {
289 /* Clamp to a multiple of 1024.
291 val = SIZE_MAX & ~(1024-1);
294 /* There's more than one character after the
301 /* The man page says that a -Xm value must be
302 * a multiple of 1024.
304 if (val % div == 0) {
314 * Handle one of the JDWP name/value pairs.
317 * help: if specified, show help message and bail
318 * transport: may be dt_socket or dt_shmem
319 * address: for dt_socket, "host:port", or just "port" when listening
320 * server: if "y", wait for debugger to attach; if "n", attach to debugger
321 * timeout: how long to wait for debugger to connect / listen
323 * Useful with server=n (these aren't supported yet):
324 * onthrow=<exception-name>: connect to debugger when exception thrown
325 * onuncaught=y|n: connect to debugger when uncaught exception thrown
326 * launch=<command-line>: launch the debugger itself
328 * The "transport" option is required, as is "address" if server=n.
330 static bool handleJdwpOption(const char* name, const char* value)
332 if (strcmp(name, "transport") == 0) {
333 if (strcmp(value, "dt_socket") == 0) {
334 gDvm.jdwpTransport = kJdwpTransportSocket;
335 } else if (strcmp(value, "dt_android_adb") == 0) {
336 gDvm.jdwpTransport = kJdwpTransportAndroidAdb;
338 LOGE("JDWP transport '%s' not supported\n", value);
341 } else if (strcmp(name, "server") == 0) {
343 gDvm.jdwpServer = false;
344 else if (*value == 'y')
345 gDvm.jdwpServer = true;
347 LOGE("JDWP option 'server' must be 'y' or 'n'\n");
350 } else if (strcmp(name, "suspend") == 0) {
352 gDvm.jdwpSuspend = false;
353 else if (*value == 'y')
354 gDvm.jdwpSuspend = true;
356 LOGE("JDWP option 'suspend' must be 'y' or 'n'\n");
359 } else if (strcmp(name, "address") == 0) {
360 /* this is either <port> or <host>:<port> */
361 const char* colon = strchr(value, ':');
367 gDvm.jdwpHost = (char*) malloc(colon - value +1);
368 strncpy(gDvm.jdwpHost, value, colon - value +1);
369 gDvm.jdwpHost[colon-value] = '\0';
372 if (*value == '\0') {
373 LOGE("JDWP address missing port\n");
376 port = strtol(value, &end, 10);
378 LOGE("JDWP address has junk in port field '%s'\n", value);
381 gDvm.jdwpPort = port;
382 } else if (strcmp(name, "launch") == 0 ||
383 strcmp(name, "onthrow") == 0 ||
384 strcmp(name, "oncaught") == 0 ||
385 strcmp(name, "timeout") == 0)
387 /* valid but unsupported */
388 LOGI("Ignoring JDWP option '%s'='%s'\n", name, value);
390 LOGI("Ignoring unrecognized JDWP option '%s'='%s'\n", name, value);
397 * Parse the latter half of a -Xrunjdwp/-agentlib:jdwp= string, e.g.:
398 * "transport=dt_socket,address=8000,server=y,suspend=n"
400 static bool parseJdwpOptions(const char* str)
402 char* mangle = strdup(str);
407 * Process all of the name=value pairs.
413 value = strchr(name, '=');
415 LOGE("JDWP opts: garbage at '%s'\n", name);
419 comma = strchr(name, ','); // use name, not value, for safety
422 LOGE("JDWP opts: found comma before '=' in '%s'\n", mangle);
428 *value++ = '\0'; // stomp the '='
430 if (!handleJdwpOption(name, value))
441 * Make sure the combination of arguments makes sense.
443 if (gDvm.jdwpTransport == kJdwpTransportUnknown) {
444 LOGE("JDWP opts: must specify transport\n");
447 if (!gDvm.jdwpServer && (gDvm.jdwpHost == NULL || gDvm.jdwpPort == 0)) {
448 LOGE("JDWP opts: when server=n, must specify host and port\n");
451 // transport mandatory
452 // outbound server address
454 gDvm.jdwpConfigured = true;
463 * Handle one of the four kinds of assertion arguments.
465 * "pkgOrClass" is the last part of an enable/disable line. For a package
466 * the arg looks like "-ea:com.google.fubar...", for a class it looks
467 * like "-ea:com.google.fubar.Wahoo". The string we get starts at the ':'.
469 * For system assertions (-esa/-dsa), "pkgOrClass" is NULL.
471 * Multiple instances of these arguments can be specified, e.g. you can
472 * enable assertions for a package and then disable them for one class in
475 static bool enableAssertions(const char* pkgOrClass, bool enable)
477 AssertionControl* pCtrl = &gDvm.assertionCtrl[gDvm.assertionCtrlCount++];
478 pCtrl->enable = enable;
480 if (pkgOrClass == NULL) {
481 /* enable or disable for all system classes */
482 pCtrl->isPackage = false;
483 pCtrl->pkgOrClass = NULL;
484 pCtrl->pkgOrClassLen = 0;
486 if (*pkgOrClass == '\0') {
487 /* global enable/disable for all but system */
488 pCtrl->isPackage = false;
489 pCtrl->pkgOrClass = strdup("");
490 pCtrl->pkgOrClassLen = 0;
492 pCtrl->pkgOrClass = dvmDotToSlash(pkgOrClass+1); // skip ':'
493 if (pCtrl->pkgOrClass == NULL) {
494 /* can happen if class name includes an illegal '/' */
495 LOGW("Unable to process assertion arg '%s'\n", pkgOrClass);
499 int len = strlen(pCtrl->pkgOrClass);
500 if (len >= 3 && strcmp(pCtrl->pkgOrClass + len-3, "///") == 0) {
501 /* mark as package, truncate two of the three slashes */
502 pCtrl->isPackage = true;
503 *(pCtrl->pkgOrClass + len-2) = '\0';
504 pCtrl->pkgOrClassLen = len - 2;
507 pCtrl->isPackage = false;
508 pCtrl->pkgOrClassLen = len;
517 * Turn assertions on when requested to do so by the Zygote.
519 * This is a bit sketchy. We can't (easily) go back and fiddle with all
520 * of the classes that have already been initialized, so this only
521 * affects classes that have yet to be loaded. If some or all assertions
522 * have been enabled through some other means, we don't want to mess with
523 * it here, so we do nothing. Finally, we assume that there's room in
524 * "assertionCtrl" to hold at least one entry; this is guaranteed by the
527 * This must only be called from the main thread during zygote init.
529 void dvmLateEnableAssertions(void)
531 if (gDvm.assertionCtrl == NULL) {
532 LOGD("Not late-enabling assertions: no assertionCtrl array\n");
534 } else if (gDvm.assertionCtrlCount != 0) {
535 LOGD("Not late-enabling assertions: some asserts already configured\n");
538 LOGD("Late-enabling assertions\n");
540 /* global enable for all but system */
541 AssertionControl* pCtrl = gDvm.assertionCtrl;
542 pCtrl->pkgOrClass = strdup("");
543 pCtrl->pkgOrClassLen = 0;
544 pCtrl->isPackage = false;
545 pCtrl->enable = true;
546 gDvm.assertionCtrlCount = 1;
551 * Release memory associated with the AssertionCtrl array.
553 static void freeAssertionCtrl(void)
557 for (i = 0; i < gDvm.assertionCtrlCount; i++)
558 free(gDvm.assertionCtrl[i].pkgOrClass);
559 free(gDvm.assertionCtrl);
562 #if defined(WITH_JIT)
563 /* Parse -Xjitop to selectively turn on/off certain opcodes for JIT */
564 static void processXjitop(const char *opt)
567 const char *startPtr = &opt[8];
571 long startValue, endValue;
573 startValue = strtol(startPtr, &endPtr, 16);
574 if (startPtr != endPtr) {
575 /* Just in case value is out of range */
578 if (*endPtr == '-') {
579 endValue = strtol(endPtr+1, &endPtr, 16);
582 endValue = startValue;
585 for (; startValue <= endValue; startValue++) {
586 LOGW("Dalvik opcode %x is selected for debugging",
587 (unsigned int) startValue);
588 /* Mark the corresponding bit to 1 */
589 gDvmJit.opList[startValue >> 3] |=
590 1 << (startValue & 0x7);
597 startPtr = endPtr + 1;
603 "Warning: Unrecognized opcode value substring "
611 for (i = 0; i < 32; i++) {
612 gDvmJit.opList[i] = 0xff;
614 dvmFprintf(stderr, "Warning: select all opcodes\n");
618 /* Parse -Xjitmethod to selectively turn on/off certain methods for JIT */
619 static void processXjitmethod(const char *opt)
621 char *buf = strdup(&opt[12]);
624 gDvmJit.methodTable = dvmHashTableCreate(8, NULL);
628 * Break comma-separated method signatures and enter them into the hash
629 * table individually.
634 end = strchr(start, ',');
639 hashValue = dvmComputeUtf8Hash(start);
641 dvmHashTableLookup(gDvmJit.methodTable, hashValue,
643 (HashCompareFunc) strcmp, true);
655 * Process an argument vector full of options. Unlike standard C programs,
656 * argv[0] does not contain the name of the program.
658 * If "ignoreUnrecognized" is set, we ignore options starting with "-X" or "_"
659 * that we don't recognize. Otherwise, we return with an error as soon as
660 * we see anything we can't identify.
662 * Returns 0 on success, -1 on failure, and 1 for the special case of
663 * "-version" where we want to stop without showing an error message.
665 static int processOptions(int argc, const char* const argv[],
666 bool ignoreUnrecognized)
670 LOGV("VM options (%d):\n", argc);
671 for (i = 0; i < argc; i++)
672 LOGV(" %d: '%s'\n", i, argv[i]);
675 * Over-allocate AssertionControl array for convenience. If allocated,
676 * the array must be able to hold at least one entry, so that the
677 * zygote-time activation can do its business.
679 assert(gDvm.assertionCtrl == NULL);
682 (AssertionControl*) malloc(sizeof(AssertionControl) * argc);
683 if (gDvm.assertionCtrl == NULL)
685 assert(gDvm.assertionCtrlCount == 0);
688 for (i = 0; i < argc; i++) {
689 if (strcmp(argv[i], "-help") == 0) {
690 /* show usage and stop */
693 } else if (strcmp(argv[i], "-version") == 0) {
694 /* show version and stop */
697 } else if (strcmp(argv[i], "-showversion") == 0) {
698 /* show version and continue */
701 } else if (strcmp(argv[i], "-classpath") == 0 ||
702 strcmp(argv[i], "-cp") == 0)
706 dvmFprintf(stderr, "Missing classpath path list\n");
709 free(gDvm.classPathStr); /* in case we have compiled-in default */
710 gDvm.classPathStr = strdup(argv[++i]);
712 } else if (strncmp(argv[i], "-Xbootclasspath:",
713 sizeof("-Xbootclasspath:")-1) == 0)
715 /* set bootclasspath */
716 const char* path = argv[i] + sizeof("-Xbootclasspath:")-1;
719 dvmFprintf(stderr, "Missing bootclasspath path list\n");
722 free(gDvm.bootClassPathStr);
723 gDvm.bootClassPathStr = strdup(path);
725 } else if (strncmp(argv[i], "-Xbootclasspath/a:",
726 sizeof("-Xbootclasspath/a:")-1) == 0) {
727 const char* appPath = argv[i] + sizeof("-Xbootclasspath/a:")-1;
729 if (*(appPath) == '\0') {
730 dvmFprintf(stderr, "Missing appending bootclasspath path list\n");
735 if (asprintf(&allPath, "%s:%s", gDvm.bootClassPathStr, appPath) < 0) {
736 dvmFprintf(stderr, "Can't append to bootclasspath path list\n");
739 free(gDvm.bootClassPathStr);
740 gDvm.bootClassPathStr = allPath;
742 } else if (strncmp(argv[i], "-Xbootclasspath/p:",
743 sizeof("-Xbootclasspath/p:")-1) == 0) {
744 const char* prePath = argv[i] + sizeof("-Xbootclasspath/p:")-1;
746 if (*(prePath) == '\0') {
747 dvmFprintf(stderr, "Missing prepending bootclasspath path list\n");
752 if (asprintf(&allPath, "%s:%s", prePath, gDvm.bootClassPathStr) < 0) {
753 dvmFprintf(stderr, "Can't prepend to bootclasspath path list\n");
756 free(gDvm.bootClassPathStr);
757 gDvm.bootClassPathStr = allPath;
759 } else if (strncmp(argv[i], "-D", 2) == 0) {
761 dvmAddCommandLineProperty(argv[i] + 2);
763 } else if (strcmp(argv[i], "-jar") == 0) {
764 // TODO: handle this; name of jar should be in argv[i+1]
765 dvmFprintf(stderr, "-jar not yet handled\n");
768 } else if (strncmp(argv[i], "-Xms", 4) == 0) {
769 size_t val = parseMemOption(argv[i]+4, 1024);
771 if (val >= kMinHeapStartSize && val <= kMaxHeapSize) {
772 gDvm.heapStartingSize = val;
775 "Invalid -Xms '%s', range is %dKB to %dKB\n",
776 argv[i], kMinHeapStartSize/1024, kMaxHeapSize/1024);
780 dvmFprintf(stderr, "Invalid -Xms option '%s'\n", argv[i]);
783 } else if (strncmp(argv[i], "-Xmx", 4) == 0) {
784 size_t val = parseMemOption(argv[i]+4, 1024);
786 if (val >= kMinHeapSize && val <= kMaxHeapSize) {
787 gDvm.heapMaximumSize = val;
790 "Invalid -Xmx '%s', range is %dKB to %dKB\n",
791 argv[i], kMinHeapSize/1024, kMaxHeapSize/1024);
795 dvmFprintf(stderr, "Invalid -Xmx option '%s'\n", argv[i]);
798 } else if (strncmp(argv[i], "-XX:HeapGrowthLimit=", 20) == 0) {
799 size_t val = parseMemOption(argv[i] + 20, 1024);
801 gDvm.heapGrowthLimit = val;
803 dvmFprintf(stderr, "Invalid -XX:HeapGrowthLimit option '%s'\n", argv[i]);
806 } else if (strncmp(argv[i], "-Xss", 4) == 0) {
807 size_t val = parseMemOption(argv[i]+4, 1);
809 if (val >= kMinStackSize && val <= kMaxStackSize) {
810 gDvm.stackSize = val;
812 dvmFprintf(stderr, "Invalid -Xss '%s', range is %d to %d\n",
813 argv[i], kMinStackSize, kMaxStackSize);
817 dvmFprintf(stderr, "Invalid -Xss option '%s'\n", argv[i]);
821 } else if (strncmp(argv[i], "-XX:+DisableExplicitGC", 22) == 0) {
822 gDvm.disableExplicitGc = true;
823 } else if (strcmp(argv[i], "-verbose") == 0 ||
824 strcmp(argv[i], "-verbose:class") == 0)
826 // JNI spec says "-verbose:gc,class" is valid, but cmd line
827 // doesn't work that way; may want to support.
828 gDvm.verboseClass = true;
829 } else if (strcmp(argv[i], "-verbose:jni") == 0) {
830 gDvm.verboseJni = true;
831 } else if (strcmp(argv[i], "-verbose:gc") == 0) {
832 gDvm.verboseGc = true;
833 } else if (strcmp(argv[i], "-verbose:shutdown") == 0) {
834 gDvm.verboseShutdown = true;
836 } else if (strncmp(argv[i], "-enableassertions", 17) == 0) {
837 enableAssertions(argv[i] + 17, true);
838 } else if (strncmp(argv[i], "-ea", 3) == 0) {
839 enableAssertions(argv[i] + 3, true);
840 } else if (strncmp(argv[i], "-disableassertions", 18) == 0) {
841 enableAssertions(argv[i] + 18, false);
842 } else if (strncmp(argv[i], "-da", 3) == 0) {
843 enableAssertions(argv[i] + 3, false);
844 } else if (strcmp(argv[i], "-enablesystemassertions") == 0 ||
845 strcmp(argv[i], "-esa") == 0)
847 enableAssertions(NULL, true);
848 } else if (strcmp(argv[i], "-disablesystemassertions") == 0 ||
849 strcmp(argv[i], "-dsa") == 0)
851 enableAssertions(NULL, false);
853 } else if (strncmp(argv[i], "-Xcheck:jni", 11) == 0) {
854 /* nothing to do now -- was handled during JNI init */
856 } else if (strcmp(argv[i], "-Xdebug") == 0) {
857 /* accept but ignore */
859 } else if (strncmp(argv[i], "-Xrunjdwp:", 10) == 0 ||
860 strncmp(argv[i], "-agentlib:jdwp=", 15) == 0)
864 if (argv[i][1] == 'X')
869 if (strncmp(tail, "help", 4) == 0 || !parseJdwpOptions(tail)) {
873 } else if (strcmp(argv[i], "-Xrs") == 0) {
874 gDvm.reduceSignals = true;
875 } else if (strcmp(argv[i], "-Xnoquithandler") == 0) {
876 /* disables SIGQUIT handler thread while still blocking SIGQUIT */
877 /* (useful if we don't want thread but system still signals us) */
878 gDvm.noQuitHandler = true;
879 } else if (strcmp(argv[i], "-Xzygote") == 0) {
881 #if defined(WITH_JIT)
882 gDvmJit.runningInAndroidFramework = true;
884 } else if (strncmp(argv[i], "-Xdexopt:", 9) == 0) {
885 if (strcmp(argv[i] + 9, "none") == 0)
886 gDvm.dexOptMode = OPTIMIZE_MODE_NONE;
887 else if (strcmp(argv[i] + 9, "verified") == 0)
888 gDvm.dexOptMode = OPTIMIZE_MODE_VERIFIED;
889 else if (strcmp(argv[i] + 9, "all") == 0)
890 gDvm.dexOptMode = OPTIMIZE_MODE_ALL;
892 dvmFprintf(stderr, "Unrecognized dexopt option '%s'\n",argv[i]);
895 } else if (strncmp(argv[i], "-Xverify:", 9) == 0) {
896 if (strcmp(argv[i] + 9, "none") == 0)
897 gDvm.classVerifyMode = VERIFY_MODE_NONE;
898 else if (strcmp(argv[i] + 9, "remote") == 0)
899 gDvm.classVerifyMode = VERIFY_MODE_REMOTE;
900 else if (strcmp(argv[i] + 9, "all") == 0)
901 gDvm.classVerifyMode = VERIFY_MODE_ALL;
903 dvmFprintf(stderr, "Unrecognized verify option '%s'\n",argv[i]);
906 } else if (strncmp(argv[i], "-Xjnigreflimit:", 15) == 0) {
907 int lim = atoi(argv[i] + 15);
908 if (lim < 200 || (lim % 100) != 0) {
909 dvmFprintf(stderr, "Bad value for -Xjnigreflimit: '%s'\n",
913 gDvm.jniGrefLimit = lim;
914 } else if (strncmp(argv[i], "-Xjnitrace:", 11) == 0) {
915 gDvm.jniTrace = strdup(argv[i] + 11);
916 } else if (strcmp(argv[i], "-Xlog-stdio") == 0) {
917 gDvm.logStdio = true;
919 } else if (strncmp(argv[i], "-Xint", 5) == 0) {
920 if (argv[i][5] == ':') {
921 if (strcmp(argv[i] + 6, "portable") == 0)
922 gDvm.executionMode = kExecutionModeInterpPortable;
923 else if (strcmp(argv[i] + 6, "fast") == 0)
924 gDvm.executionMode = kExecutionModeInterpFast;
926 else if (strcmp(argv[i] + 6, "jit") == 0)
927 gDvm.executionMode = kExecutionModeJit;
931 "Warning: Unrecognized interpreter mode %s\n",argv[i]);
935 /* disable JIT if it was enabled by default */
936 gDvm.executionMode = kExecutionModeInterpFast;
939 } else if (strncmp(argv[i], "-Xlockprofthreshold:", 20) == 0) {
940 gDvm.lockProfThreshold = atoi(argv[i] + 20);
943 } else if (strncmp(argv[i], "-Xjitop", 7) == 0) {
944 processXjitop(argv[i]);
945 } else if (strncmp(argv[i], "-Xjitmethod", 11) == 0) {
946 processXjitmethod(argv[i]);
947 } else if (strncmp(argv[i], "-Xjitblocking", 13) == 0) {
948 gDvmJit.blockingMode = true;
949 } else if (strncmp(argv[i], "-Xjitthreshold:", 15) == 0) {
950 gDvmJit.threshold = atoi(argv[i] + 15);
951 } else if (strncmp(argv[i], "-Xincludeselectedop", 19) == 0) {
952 gDvmJit.includeSelectedOp = true;
953 } else if (strncmp(argv[i], "-Xincludeselectedmethod", 23) == 0) {
954 gDvmJit.includeSelectedMethod = true;
955 } else if (strncmp(argv[i], "-Xjitcheckcg", 12) == 0) {
956 gDvmJit.checkCallGraph = true;
957 /* Need to enable blocking mode due to stack crawling */
958 gDvmJit.blockingMode = true;
959 } else if (strncmp(argv[i], "-Xjitverbose", 12) == 0) {
960 gDvmJit.printMe = true;
961 } else if (strncmp(argv[i], "-Xjitprofile", 12) == 0) {
962 gDvmJit.profile = true;
963 } else if (strncmp(argv[i], "-Xjitdisableopt", 15) == 0) {
964 /* Disable selected optimizations */
965 if (argv[i][15] == ':') {
966 sscanf(argv[i] + 16, "%x", &gDvmJit.disableOpt);
967 /* Disable all optimizations */
969 gDvmJit.disableOpt = -1;
973 } else if (strncmp(argv[i], "-Xdeadlockpredict:", 18) == 0) {
974 #ifdef WITH_DEADLOCK_PREDICTION
975 if (strcmp(argv[i] + 18, "off") == 0)
976 gDvm.deadlockPredictMode = kDPOff;
977 else if (strcmp(argv[i] + 18, "warn") == 0)
978 gDvm.deadlockPredictMode = kDPWarn;
979 else if (strcmp(argv[i] + 18, "err") == 0)
980 gDvm.deadlockPredictMode = kDPErr;
981 else if (strcmp(argv[i] + 18, "abort") == 0)
982 gDvm.deadlockPredictMode = kDPAbort;
984 dvmFprintf(stderr, "Bad value for -Xdeadlockpredict");
987 if (gDvm.deadlockPredictMode != kDPOff)
988 LOGD("Deadlock prediction enabled (%s)\n", argv[i]+18);
991 } else if (strncmp(argv[i], "-Xstacktracefile:", 17) == 0) {
992 gDvm.stackTraceFile = strdup(argv[i]+17);
994 } else if (strcmp(argv[i], "-Xgenregmap") == 0) {
995 gDvm.generateRegisterMaps = true;
996 LOGV("Register maps will be generated during verification\n");
998 } else if (strcmp(argv[i], "Xverifyopt:checkmon") == 0) {
999 gDvm.monitorVerification = true;
1000 } else if (strcmp(argv[i], "Xverifyopt:nocheckmon") == 0) {
1001 gDvm.monitorVerification = false;
1003 } else if (strncmp(argv[i], "-Xgc:", 5) == 0) {
1004 if (strcmp(argv[i] + 5, "precise") == 0)
1005 gDvm.preciseGc = true;
1006 else if (strcmp(argv[i] + 5, "noprecise") == 0)
1007 gDvm.preciseGc = false;
1008 else if (strcmp(argv[i] + 5, "preverify") == 0)
1009 gDvm.preVerify = true;
1010 else if (strcmp(argv[i] + 5, "nopreverify") == 0)
1011 gDvm.preVerify = false;
1012 else if (strcmp(argv[i] + 5, "postverify") == 0)
1013 gDvm.postVerify = true;
1014 else if (strcmp(argv[i] + 5, "nopostverify") == 0)
1015 gDvm.postVerify = false;
1016 else if (strcmp(argv[i] + 5, "concurrent") == 0)
1017 gDvm.concurrentMarkSweep = true;
1018 else if (strcmp(argv[i] + 5, "noconcurrent") == 0)
1019 gDvm.concurrentMarkSweep = false;
1020 else if (strcmp(argv[i] + 5, "verifycardtable") == 0)
1021 gDvm.verifyCardTable = true;
1022 else if (strcmp(argv[i] + 5, "noverifycardtable") == 0)
1023 gDvm.verifyCardTable = false;
1025 dvmFprintf(stderr, "Bad value for -Xgc");
1028 LOGV("Precise GC configured %s\n", gDvm.preciseGc ? "ON" : "OFF");
1030 } else if (strcmp(argv[i], "-Xcheckdexsum") == 0) {
1031 gDvm.verifyDexChecksum = true;
1033 } else if (strcmp(argv[i], "-Xprofile:wallclock") == 0) {
1034 gDvm.profilerWallClock = true;
1037 if (!ignoreUnrecognized) {
1038 dvmFprintf(stderr, "Unrecognized option '%s'\n", argv[i]);
1048 * Set defaults for fields altered or modified by arguments.
1050 * Globals are initialized to 0 (a/k/a NULL or false).
1052 static void setCommandLineDefaults()
1056 envStr = getenv("CLASSPATH");
1058 gDvm.classPathStr = strdup(envStr);
1060 gDvm.classPathStr = strdup(".");
1061 envStr = getenv("BOOTCLASSPATH");
1063 gDvm.bootClassPathStr = strdup(envStr);
1065 gDvm.bootClassPathStr = strdup(".");
1067 /* Defaults overridden by -Xms and -Xmx.
1068 * TODO: base these on a system or application-specific default
1070 gDvm.heapStartingSize = 2 * 1024 * 1024; // Spec says 16MB; too big for us.
1071 gDvm.heapMaximumSize = 16 * 1024 * 1024; // Spec says 75% physical mem
1072 gDvm.heapGrowthLimit = 0; // 0 means no growth limit
1073 gDvm.stackSize = kDefaultStackSize;
1075 gDvm.concurrentMarkSweep = true;
1077 /* gDvm.jdwpSuspend = true; */
1079 /* allowed unless zygote config doesn't allow it */
1080 gDvm.jdwpAllowed = true;
1082 /* default verification and optimization modes */
1083 gDvm.classVerifyMode = VERIFY_MODE_ALL;
1084 gDvm.dexOptMode = OPTIMIZE_MODE_VERIFIED;
1085 gDvm.monitorVerification = false;
1088 * Default execution mode.
1090 * This should probably interact with the mterp code somehow, e.g. if
1091 * we know we're using the "desktop" build we should probably be
1092 * using "portable" rather than "fast".
1094 #if defined(WITH_JIT)
1095 gDvm.executionMode = kExecutionModeJit;
1097 gDvm.executionMode = kExecutionModeInterpFast;
1101 * SMP support is a compile-time define, but we may want to have
1102 * dexopt target a differently-configured device.
1104 gDvm.dexOptForSmp = (ANDROID_SMP != 0);
1109 * Handle a SIGBUS, which frequently occurs because somebody replaced an
1110 * optimized DEX file out from under us.
1112 static void busCatcher(int signum, siginfo_t* info, void* context)
1114 void* addr = info->si_addr;
1116 LOGE("Caught a SIGBUS (%d), addr=%p\n", signum, addr);
1119 * If we return at this point the SIGBUS just keeps happening, so we
1120 * remove the signal handler and allow it to kill us. TODO: restore
1121 * the original, which points to a debuggerd stub; if we don't then
1122 * debuggerd won't be notified.
1124 signal(SIGBUS, SIG_DFL);
1128 * Configure signals. We need to block SIGQUIT so that the signal only
1129 * reaches the dump-stack-trace thread.
1131 * This can be disabled with the "-Xrs" flag.
1133 static void blockSignals()
1139 sigaddset(&mask, SIGQUIT);
1140 sigaddset(&mask, SIGUSR1); // used to initiate heap dump
1141 #if defined(WITH_JIT) && defined(WITH_JIT_TUNING)
1142 sigaddset(&mask, SIGUSR2); // used to investigate JIT internals
1144 //sigaddset(&mask, SIGPIPE);
1145 cc = sigprocmask(SIG_BLOCK, &mask, NULL);
1149 /* TODO: save the old sigaction in a global */
1150 struct sigaction sa;
1151 memset(&sa, 0, sizeof(sa));
1152 sa.sa_sigaction = busCatcher;
1153 sa.sa_flags = SA_SIGINFO;
1154 cc = sigaction(SIGBUS, &sa, NULL);
1160 * VM initialization. Pass in any options provided on the command line.
1161 * Do not pass in the class name or the options for the class.
1163 * Returns 0 on success.
1165 int dvmStartup(int argc, const char* const argv[], bool ignoreUnrecognized,
1170 assert(gDvm.initializing);
1172 LOGV("VM init args (%d):\n", argc);
1173 for (i = 0; i < argc; i++)
1174 LOGV(" %d: '%s'\n", i, argv[i]);
1176 setCommandLineDefaults();
1178 /* prep properties storage */
1179 if (!dvmPropertiesStartup(argc))
1183 * Process the option flags (if any).
1185 cc = processOptions(argc, argv, ignoreUnrecognized);
1188 dvmFprintf(stderr, "\n");
1194 #if WITH_EXTRA_GC_CHECKS > 1
1195 /* only "portable" interp has the extra goodies */
1196 if (gDvm.executionMode != kExecutionModeInterpPortable) {
1197 LOGI("Switching to 'portable' interpreter for GC checks\n");
1198 gDvm.executionMode = kExecutionModeInterpPortable;
1202 /* Configure group scheduling capabilities */
1203 if (!access("/dev/cpuctl/tasks", F_OK)) {
1204 LOGV("Using kernel group scheduling");
1205 gDvm.kernelGroupScheduling = 1;
1207 LOGV("Using kernel scheduler policies");
1210 /* configure signal handling */
1211 if (!gDvm.reduceSignals)
1214 /* verify system page size */
1215 if (sysconf(_SC_PAGESIZE) != SYSTEM_PAGE_SIZE) {
1216 LOGE("ERROR: expected page size %d, got %d\n",
1217 SYSTEM_PAGE_SIZE, (int) sysconf(_SC_PAGESIZE));
1222 LOGV("Using executionMode %d\n", gDvm.executionMode);
1223 dvmCheckAsmConstants();
1226 * Initialize components.
1228 if (!dvmAllocTrackerStartup())
1230 if (!dvmGcStartup())
1232 if (!dvmThreadStartup())
1234 if (!dvmInlineNativeStartup())
1236 if (!dvmRegisterMapStartup())
1238 if (!dvmInstanceofStartup())
1240 if (!dvmClassStartup())
1242 if (!dvmBaseClassStartup())
1244 if (!dvmThreadObjStartup())
1246 if (!dvmExceptionStartup())
1248 if (!dvmStringInternStartup())
1250 if (!dvmNativeStartup())
1252 if (!dvmInternalNativeStartup())
1254 if (!dvmJniStartup())
1256 if (!dvmReflectStartup())
1258 if (!dvmProfilingStartup())
1261 /* make sure we got these [can this go away?] */
1262 assert(gDvm.classJavaLangClass != NULL);
1263 assert(gDvm.classJavaLangObject != NULL);
1264 //assert(gDvm.classJavaLangString != NULL);
1265 assert(gDvm.classJavaLangThread != NULL);
1266 assert(gDvm.classJavaLangVMThread != NULL);
1267 assert(gDvm.classJavaLangThreadGroup != NULL);
1270 * Make sure these exist. If they don't, we can return a failure out
1271 * of main and nip the whole thing in the bud.
1273 static const char* earlyClasses[] = {
1274 "Ljava/lang/InternalError;",
1275 "Ljava/lang/StackOverflowError;",
1276 "Ljava/lang/UnsatisfiedLinkError;",
1277 "Ljava/lang/NoClassDefFoundError;",
1280 const char** pClassName;
1281 for (pClassName = earlyClasses; *pClassName != NULL; pClassName++) {
1282 if (dvmFindSystemClassNoInit(*pClassName) == NULL)
1287 * Miscellaneous class library validation.
1289 if (!dvmValidateBoxClasses())
1293 * Do the last bits of Thread struct initialization we need to allow
1294 * JNI calls to work.
1296 if (!dvmPrepMainForJni(pEnv))
1300 * Explicitly initialize java.lang.Class. This doesn't happen
1301 * automatically because it's allocated specially (it's an instance
1302 * of itself). Must happen before registration of system natives,
1303 * which make some calls that throw assertions if the classes they
1304 * operate on aren't initialized.
1306 if (!dvmInitClass(gDvm.classJavaLangClass))
1310 * Register the system native methods, which are registered through JNI.
1312 if (!registerSystemNatives(pEnv))
1316 * Do some "late" initialization for the memory allocator. This may
1317 * allocate storage and initialize classes.
1319 if (!dvmCreateStockExceptions())
1323 * At this point, the VM is in a pretty good state. Finish prep on
1324 * the main thread (specifically, create a java.lang.Thread object to go
1325 * along with our Thread struct). Note we will probably be executing
1326 * some interpreted class initializer code in here.
1328 if (!dvmPrepMainThread())
1332 * Make sure we haven't accumulated any tracked references. The main
1333 * thread should be starting with a clean slate.
1335 if (dvmReferenceTableEntries(&dvmThreadSelf()->internalLocalRefTable) != 0)
1337 LOGW("Warning: tracked references remain post-initialization\n");
1338 dvmDumpReferenceTable(&dvmThreadSelf()->internalLocalRefTable, "MAIN");
1341 /* general debugging setup */
1342 if (!dvmDebuggerStartup())
1345 if (!dvmInlineNativeCheck())
1349 * Init for either zygote mode or non-zygote mode. The key difference
1350 * is that we don't start any additional threads in Zygote mode.
1356 if (!dvmInitAfterZygote())
1363 LOGE("dmvTestHash FAILED\n");
1364 if (false /*noisy!*/ && !dvmTestIndirectRefTable())
1365 LOGE("dvmTestIndirectRefTable FAILED\n");
1368 assert(!dvmCheckException(dvmThreadSelf()));
1369 gDvm.initExceptionCount = 0;
1379 * Register java.* natives from our class libraries. We need to do
1380 * this after we're ready for JNI registration calls, but before we
1381 * do any class initialization.
1383 * If we get this wrong, we will blow up in the ThreadGroup class init if
1384 * interpreted code makes any reference to System. It will likely do this
1385 * since it wants to do some java.io.File setup (e.g. for static in/out/err).
1387 * We need to have gDvm.initializing raised here so that JNI FindClass
1388 * won't try to use the system/application class loader.
1390 static bool registerSystemNatives(JNIEnv* pEnv)
1394 /* main thread is always first in list */
1395 self = gDvm.threadList;
1397 /* must set this before allowing JNI-based method registration */
1398 self->status = THREAD_NATIVE;
1400 if (jniRegisterSystemMethods(pEnv) < 0) {
1401 LOGE("jniRegisterSystemMethods failed");
1405 /* back to run mode */
1406 self->status = THREAD_RUNNING;
1413 * Do zygote-mode-only initialization.
1415 static bool initZygote(void)
1417 /* zygote goes into its own process group */
1424 * Do non-zygote-mode initialization. This is done during VM init for
1425 * standard startup, or after a "zygote fork" when creating a new process.
1427 bool dvmInitAfterZygote(void)
1429 u8 startHeap, startQuit, startJdwp;
1430 u8 endHeap, endQuit, endJdwp;
1432 startHeap = dvmGetRelativeTimeUsec();
1435 * Post-zygote heap initialization, including starting
1436 * the HeapWorker thread.
1438 if (!dvmGcStartupAfterZygote())
1441 endHeap = dvmGetRelativeTimeUsec();
1442 startQuit = dvmGetRelativeTimeUsec();
1444 /* start signal catcher thread that dumps stacks on SIGQUIT */
1445 if (!gDvm.reduceSignals && !gDvm.noQuitHandler) {
1446 if (!dvmSignalCatcherStartup())
1450 /* start stdout/stderr copier, if requested */
1451 if (gDvm.logStdio) {
1452 if (!dvmStdioConverterStartup())
1456 endQuit = dvmGetRelativeTimeUsec();
1457 startJdwp = dvmGetRelativeTimeUsec();
1460 * Start JDWP thread. If the command-line debugger flags specified
1461 * "suspend=y", this will pause the VM. We probably want this to
1465 LOGD("JDWP init failed; continuing anyway\n");
1468 endJdwp = dvmGetRelativeTimeUsec();
1470 LOGV("thread-start heap=%d quit=%d jdwp=%d total=%d usec\n",
1471 (int)(endHeap-startHeap), (int)(endQuit-startQuit),
1472 (int)(endJdwp-startJdwp), (int)(endJdwp-startHeap));
1475 if (gDvm.executionMode == kExecutionModeJit) {
1476 if (!dvmCompilerStartup())
1485 * Prepare for a connection to a JDWP-compliant debugger.
1487 * Note this needs to happen fairly late in the startup process, because
1488 * we need to have all of the java.* native methods registered (which in
1489 * turn requires JNI to be fully prepped).
1491 * There are several ways to initialize:
1493 * We immediately try to connect to host:port. Bail on failure. On
1494 * success, send VM_START (suspending the VM if "suspend=y").
1495 * server=y suspend=n
1496 * Passively listen for a debugger to connect. Return immediately.
1497 * server=y suspend=y
1498 * Wait until debugger connects. Send VM_START ASAP, suspending the
1499 * VM after the message is sent.
1501 * This gets more complicated with a nonzero value for "timeout".
1503 static bool initJdwp(void)
1505 assert(!gDvm.zygote);
1508 * Init JDWP if the debugger is enabled. This may connect out to a
1509 * debugger, passively listen for a debugger, or block waiting for a
1512 if (gDvm.jdwpAllowed && gDvm.jdwpConfigured) {
1513 JdwpStartupParams params;
1515 if (gDvm.jdwpHost != NULL) {
1516 if (strlen(gDvm.jdwpHost) >= sizeof(params.host)-1) {
1517 LOGE("ERROR: hostname too long: '%s'\n", gDvm.jdwpHost);
1520 strcpy(params.host, gDvm.jdwpHost);
1522 params.host[0] = '\0';
1524 params.transport = gDvm.jdwpTransport;
1525 params.server = gDvm.jdwpServer;
1526 params.suspend = gDvm.jdwpSuspend;
1527 params.port = gDvm.jdwpPort;
1529 gDvm.jdwpState = dvmJdwpStartup(¶ms);
1530 if (gDvm.jdwpState == NULL) {
1531 LOGW("WARNING: debugger thread failed to initialize\n");
1532 /* TODO: ignore? fail? need to mimic "expected" behavior */
1537 * If a debugger has already attached, send the "welcome" message. This
1538 * may cause us to suspend all threads.
1540 if (dvmJdwpIsActive(gDvm.jdwpState)) {
1541 //dvmChangeStatus(NULL, THREAD_RUNNING);
1542 if (!dvmJdwpPostVMStart(gDvm.jdwpState, gDvm.jdwpSuspend)) {
1543 LOGW("WARNING: failed to post 'start' message to debugger\n");
1546 //dvmChangeStatus(NULL, THREAD_NATIVE);
1553 * An alternative to JNI_CreateJavaVM/dvmStartup that does the first bit
1554 * of initialization and then returns with "initializing" still set. (Used
1555 * by DexOpt command-line utility.)
1557 * Attempting to use JNI or internal natives will fail. It's best
1558 * if no bytecode gets executed, which means no <clinit>, which means
1559 * no exception-throwing. (In practice we need to initialize Class and
1560 * Object, and probably some exception classes.)
1562 * Returns 0 on success.
1564 int dvmPrepForDexOpt(const char* bootClassPath, DexOptimizerMode dexOptMode,
1565 DexClassVerifyMode verifyMode, int dexoptFlags)
1567 gDvm.initializing = true;
1568 gDvm.optimizing = true;
1570 /* configure signal handling */
1573 /* set some defaults */
1574 setCommandLineDefaults();
1575 free(gDvm.bootClassPathStr);
1576 gDvm.bootClassPathStr = strdup(bootClassPath);
1578 /* set opt/verify modes */
1579 gDvm.dexOptMode = dexOptMode;
1580 gDvm.classVerifyMode = verifyMode;
1581 gDvm.generateRegisterMaps = (dexoptFlags & DEXOPT_GEN_REGISTER_MAPS) != 0;
1582 if (dexoptFlags & DEXOPT_SMP) {
1583 assert((dexoptFlags & DEXOPT_UNIPROCESSOR) == 0);
1584 gDvm.dexOptForSmp = true;
1585 } else if (dexoptFlags & DEXOPT_UNIPROCESSOR) {
1586 gDvm.dexOptForSmp = false;
1588 gDvm.dexOptForSmp = (ANDROID_SMP != 0);
1592 * Initialize the heap, some basic thread control mutexes, and
1593 * get the bootclasspath prepped.
1595 * We can't load any classes yet because we may not yet have a source
1596 * for things like java.lang.Object and java.lang.Class.
1598 if (!dvmGcStartup())
1600 if (!dvmThreadStartup())
1602 if (!dvmInlineNativeStartup())
1604 if (!dvmRegisterMapStartup())
1606 if (!dvmInstanceofStartup())
1608 if (!dvmClassStartup())
1612 * We leave gDvm.initializing set to "true" so that, if we're not
1613 * able to process the "core" classes, we don't go into a death-spin
1614 * trying to throw a "class not found" exception.
1626 * All threads have stopped. Finish the shutdown procedure.
1628 * We can also be called if startup fails partway through, so be prepared
1629 * to deal with partially initialized data.
1631 * Free any storage allocated in gGlobals.
1633 * We can't dlclose() shared libs we've loaded, because it's possible a
1634 * thread not associated with the VM is running code in one.
1636 * This is called from the JNI DestroyJavaVM function, which can be
1637 * called from any thread. (In practice, this will usually run in the
1638 * same thread that started the VM, a/k/a the main thread, but we don't
1639 * want to assume that.)
1641 void dvmShutdown(void)
1643 LOGV("VM shutting down\n");
1645 if (CALC_CACHE_STATS)
1646 dvmDumpAtomicCacheStats(gDvm.instanceofCache);
1649 * Stop our internal threads.
1651 dvmGcThreadShutdown();
1653 if (gDvm.jdwpState != NULL)
1654 dvmJdwpShutdown(gDvm.jdwpState);
1655 free(gDvm.jdwpHost);
1656 gDvm.jdwpHost = NULL;
1657 free(gDvm.jniTrace);
1658 gDvm.jniTrace = NULL;
1659 free(gDvm.stackTraceFile);
1660 gDvm.stackTraceFile = NULL;
1662 /* tell signal catcher to shut down if it was started */
1663 dvmSignalCatcherShutdown();
1665 /* shut down stdout/stderr conversion */
1666 dvmStdioConverterShutdown();
1669 if (gDvm.executionMode == kExecutionModeJit) {
1670 /* shut down the compiler thread */
1671 dvmCompilerShutdown();
1676 * Kill any daemon threads that still exist. Actively-running threads
1677 * are likely to crash the process if they continue to execute while
1678 * the VM shuts down.
1682 if (gDvm.verboseShutdown)
1683 LOGD("VM cleaning up\n");
1685 dvmDebuggerShutdown();
1686 dvmReflectShutdown();
1687 dvmProfilingShutdown();
1689 dvmStringInternShutdown();
1690 dvmExceptionShutdown();
1691 dvmThreadShutdown();
1693 dvmRegisterMapShutdown();
1694 dvmInstanceofShutdown();
1695 dvmInlineNativeShutdown();
1697 dvmAllocTrackerShutdown();
1698 dvmPropertiesShutdown();
1700 /* these must happen AFTER dvmClassShutdown has walked through class data */
1701 dvmNativeShutdown();
1702 dvmInternalNativeShutdown();
1704 free(gDvm.bootClassPathStr);
1705 free(gDvm.classPathStr);
1707 freeAssertionCtrl();
1710 * We want valgrind to report anything we forget to free as "definitely
1711 * lost". If there's a pointer in the global chunk, it would be reported
1712 * as "still reachable". Erasing the memory fixes this.
1714 * This must be erased to zero if we want to restart the VM within this
1717 memset(&gDvm, 0xcd, sizeof(gDvm));
1722 * fprintf() wrapper that calls through the JNI-specified vfprintf hook if
1723 * one was specified.
1725 int dvmFprintf(FILE* fp, const char* format, ...)
1730 va_start(args, format);
1731 if (gDvm.vfprintfHook != NULL)
1732 result = (*gDvm.vfprintfHook)(fp, format, args);
1734 result = vfprintf(fp, format, args);
1741 * Abort the VM. We get here on fatal errors. Try very hard not to use
1742 * this; whenever possible, return an error to somebody responsible.
1746 LOGE("VM aborting\n");
1748 fflush(NULL); // flush all open file buffers
1750 /* JNI-supplied abort hook gets right of first refusal */
1751 if (gDvm.abortHook != NULL)
1752 (*gDvm.abortHook)();
1755 * If we call abort(), all threads in the process receives a SIBABRT.
1756 * debuggerd dumps the stack trace of the main thread, whether or not
1757 * that was the thread that failed.
1759 * By stuffing a value into a bogus address, we cause a segmentation
1760 * fault in the current thread, and get a useful log from debuggerd.
1761 * We can also trivially tell the difference between a VM crash and
1762 * a deliberate abort by looking at the fault address.
1764 *((char*)0xdeadd00d) = 38;