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 dvmInitJDWP(void);
45 static bool dvmInitZygote(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 dvmUsage(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, " -Xcheckdexsum\n");
124 #if defined(WITH_JIT)
125 dvmFprintf(stderr, " -Xincludeselectedop\n");
126 dvmFprintf(stderr, " -Xjitop:hexopvalue[-endvalue]"
127 "[,hexopvalue[-endvalue]]*\n");
128 dvmFprintf(stderr, " -Xincludeselectedmethod\n");
129 dvmFprintf(stderr, " -Xjitthreshold:decimalvalue\n");
130 dvmFprintf(stderr, " -Xjitblocking\n");
131 dvmFprintf(stderr, " -Xjitmethod:signature[,signature]* "
132 "(eg Ljava/lang/String\\;replace)\n");
133 dvmFprintf(stderr, " -Xjitcheckcg\n");
134 dvmFprintf(stderr, " -Xjitverbose\n");
135 dvmFprintf(stderr, " -Xjitprofile\n");
136 dvmFprintf(stderr, " -Xjitdisableopt\n");
138 dvmFprintf(stderr, "\n");
139 dvmFprintf(stderr, "Configured with:"
142 #ifdef WITH_MONITOR_TRACKING
145 #ifdef WITH_DEADLOCK_PREDICTION
146 " deadlock_prediction"
151 #ifdef WITH_HPROF_STACK
154 #ifdef WITH_ALLOC_LIMITS
157 #ifdef WITH_TRACKREF_CHECKS
160 #ifdef WITH_INSTR_CHECKS
163 #ifdef WITH_EXTRA_OBJECT_VALIDATION
164 " extra_object_validation"
166 #ifdef WITH_EXTRA_GC_CHECKS
169 #if !defined(NDEBUG) && defined(WITH_DALVIK_ASSERT)
172 #ifdef WITH_JNI_STACK_CHECK
181 #ifdef PROFILE_FIELD_ACCESS
182 " profile_field_access"
184 #if DVM_RESOLVER_CACHE == DVM_RC_REDUCING
185 " resolver_cache_reducing"
186 #elif DVM_RESOLVER_CACHE == DVM_RC_EXPANDING
187 " resolver_cache_expanding"
188 #elif DVM_RESOLVER_CACHE == DVM_RC_NO_CACHE
189 " resolver_cache_disabled"
191 #if defined(WITH_JIT)
194 #if defined(WITH_SELF_VERIFICATION)
200 #ifdef WITH_INLINE_PROFILING
204 #ifdef DVM_SHOW_EXCEPTION
205 dvmFprintf(stderr, " show_exception=%d", DVM_SHOW_EXCEPTION);
207 dvmFprintf(stderr, "\n\n");
211 * Show helpful information on JDWP options.
213 static void showJdwpHelp(void)
216 "Example: -Xrunjdwp:transport=dt_socket,address=8000,server=y\n");
218 "Example: -Xrunjdwp:transport=dt_socket,address=localhost:6500,server=n\n");
222 * Show version and copyright info.
224 static void showVersion(void)
226 dvmFprintf(stdout, "DalvikVM version %d.%d.%d\n",
227 DALVIK_MAJOR_VERSION, DALVIK_MINOR_VERSION, DALVIK_BUG_VERSION);
229 "Copyright (C) 2007 The Android Open Source Project\n\n"
230 "This software is built from source code licensed under the "
232 "Version 2.0 (the \"License\"). You may obtain a copy of the "
234 " http://www.apache.org/licenses/LICENSE-2.0\n\n"
235 "See the associated NOTICE file for this software for further "
240 * Parse a string of the form /[0-9]+[kKmMgG]?/, which is used to specify
241 * memory sizes. [kK] indicates kilobytes, [mM] megabytes, and
244 * "s" should point just past the "-Xm?" part of the string.
245 * "min" specifies the lowest acceptable value described by "s".
246 * "div" specifies a divisor, e.g. 1024 if the value must be a multiple
249 * The spec says the -Xmx and -Xms options must be multiples of 1024. It
250 * doesn't say anything about -Xss.
252 * Returns 0 (a useless size) if "s" is malformed or specifies a low or
253 * non-evenly-divisible value.
255 static unsigned int dvmParseMemOption(const char *s, unsigned int div)
257 /* strtoul accepts a leading [+-], which we don't want,
258 * so make sure our string starts with a decimal digit.
264 val = (unsigned int)strtoul(s, (char **)&s2, 10);
266 /* s2 should be pointing just after the number.
267 * If this is the end of the string, the user
268 * has specified a number of bytes. Otherwise,
269 * there should be exactly one more character
270 * that specifies a multiplier.
275 /* The remainder of the string is either a single multiplier
276 * character, or nothing to indicate that the value is in
285 } else if (c == 'k' || c == 'K') {
287 } else if (c == 'm' || c == 'M') {
289 } else if (c == 'g' || c == 'G') {
290 mul = 1024 * 1024 * 1024;
292 /* Unknown multiplier character.
297 if (val <= UINT_MAX / mul) {
300 /* Clamp to a multiple of 1024.
302 val = UINT_MAX & ~(1024-1);
305 /* There's more than one character after the
312 /* The man page says that a -Xm value must be
313 * a multiple of 1024.
315 if (val % div == 0) {
325 * Handle one of the JDWP name/value pairs.
328 * help: if specified, show help message and bail
329 * transport: may be dt_socket or dt_shmem
330 * address: for dt_socket, "host:port", or just "port" when listening
331 * server: if "y", wait for debugger to attach; if "n", attach to debugger
332 * timeout: how long to wait for debugger to connect / listen
334 * Useful with server=n (these aren't supported yet):
335 * onthrow=<exception-name>: connect to debugger when exception thrown
336 * onuncaught=y|n: connect to debugger when uncaught exception thrown
337 * launch=<command-line>: launch the debugger itself
339 * The "transport" option is required, as is "address" if server=n.
341 static bool handleJdwpOption(const char* name, const char* value)
343 if (strcmp(name, "transport") == 0) {
344 if (strcmp(value, "dt_socket") == 0) {
345 gDvm.jdwpTransport = kJdwpTransportSocket;
346 } else if (strcmp(value, "dt_android_adb") == 0) {
347 gDvm.jdwpTransport = kJdwpTransportAndroidAdb;
349 LOGE("JDWP transport '%s' not supported\n", value);
352 } else if (strcmp(name, "server") == 0) {
354 gDvm.jdwpServer = false;
355 else if (*value == 'y')
356 gDvm.jdwpServer = true;
358 LOGE("JDWP option 'server' must be 'y' or 'n'\n");
361 } else if (strcmp(name, "suspend") == 0) {
363 gDvm.jdwpSuspend = false;
364 else if (*value == 'y')
365 gDvm.jdwpSuspend = true;
367 LOGE("JDWP option 'suspend' must be 'y' or 'n'\n");
370 } else if (strcmp(name, "address") == 0) {
371 /* this is either <port> or <host>:<port> */
372 const char* colon = strchr(value, ':');
378 gDvm.jdwpHost = (char*) malloc(colon - value +1);
379 strncpy(gDvm.jdwpHost, value, colon - value +1);
380 gDvm.jdwpHost[colon-value] = '\0';
383 if (*value == '\0') {
384 LOGE("JDWP address missing port\n");
387 port = strtol(value, &end, 10);
389 LOGE("JDWP address has junk in port field '%s'\n", value);
392 gDvm.jdwpPort = port;
393 } else if (strcmp(name, "launch") == 0 ||
394 strcmp(name, "onthrow") == 0 ||
395 strcmp(name, "oncaught") == 0 ||
396 strcmp(name, "timeout") == 0)
398 /* valid but unsupported */
399 LOGI("Ignoring JDWP option '%s'='%s'\n", name, value);
401 LOGI("Ignoring unrecognized JDWP option '%s'='%s'\n", name, value);
408 * Parse the latter half of a -Xrunjdwp/-agentlib:jdwp= string, e.g.:
409 * "transport=dt_socket,address=8000,server=y,suspend=n"
411 static bool parseJdwpOptions(const char* str)
413 char* mangle = strdup(str);
418 * Process all of the name=value pairs.
424 value = strchr(name, '=');
426 LOGE("JDWP opts: garbage at '%s'\n", name);
430 comma = strchr(name, ','); // use name, not value, for safety
433 LOGE("JDWP opts: found comma before '=' in '%s'\n", mangle);
439 *value++ = '\0'; // stomp the '='
441 if (!handleJdwpOption(name, value))
452 * Make sure the combination of arguments makes sense.
454 if (gDvm.jdwpTransport == kJdwpTransportUnknown) {
455 LOGE("JDWP opts: must specify transport\n");
458 if (!gDvm.jdwpServer && (gDvm.jdwpHost == NULL || gDvm.jdwpPort == 0)) {
459 LOGE("JDWP opts: when server=n, must specify host and port\n");
462 // transport mandatory
463 // outbound server address
465 gDvm.jdwpConfigured = true;
474 * Handle one of the four kinds of assertion arguments.
476 * "pkgOrClass" is the last part of an enable/disable line. For a package
477 * the arg looks like "-ea:com.google.fubar...", for a class it looks
478 * like "-ea:com.google.fubar.Wahoo". The string we get starts at the ':'.
480 * For system assertions (-esa/-dsa), "pkgOrClass" is NULL.
482 * Multiple instances of these arguments can be specified, e.g. you can
483 * enable assertions for a package and then disable them for one class in
486 static bool enableAssertions(const char* pkgOrClass, bool enable)
488 AssertionControl* pCtrl = &gDvm.assertionCtrl[gDvm.assertionCtrlCount++];
489 pCtrl->enable = enable;
491 if (pkgOrClass == NULL) {
492 /* enable or disable for all system classes */
493 pCtrl->isPackage = false;
494 pCtrl->pkgOrClass = NULL;
495 pCtrl->pkgOrClassLen = 0;
497 if (*pkgOrClass == '\0') {
498 /* global enable/disable for all but system */
499 pCtrl->isPackage = false;
500 pCtrl->pkgOrClass = strdup("");
501 pCtrl->pkgOrClassLen = 0;
503 pCtrl->pkgOrClass = dvmDotToSlash(pkgOrClass+1); // skip ':'
504 if (pCtrl->pkgOrClass == NULL) {
505 /* can happen if class name includes an illegal '/' */
506 LOGW("Unable to process assertion arg '%s'\n", pkgOrClass);
510 int len = strlen(pCtrl->pkgOrClass);
511 if (len >= 3 && strcmp(pCtrl->pkgOrClass + len-3, "///") == 0) {
512 /* mark as package, truncate two of the three slashes */
513 pCtrl->isPackage = true;
514 *(pCtrl->pkgOrClass + len-2) = '\0';
515 pCtrl->pkgOrClassLen = len - 2;
518 pCtrl->isPackage = false;
519 pCtrl->pkgOrClassLen = len;
528 * Turn assertions on when requested to do so by the Zygote.
530 * This is a bit sketchy. We can't (easily) go back and fiddle with all
531 * of the classes that have already been initialized, so this only
532 * affects classes that have yet to be loaded. If some or all assertions
533 * have been enabled through some other means, we don't want to mess with
534 * it here, so we do nothing. Finally, we assume that there's room in
535 * "assertionCtrl" to hold at least one entry; this is guaranteed by the
538 * This must only be called from the main thread during zygote init.
540 void dvmLateEnableAssertions(void)
542 if (gDvm.assertionCtrl == NULL) {
543 LOGD("Not late-enabling assertions: no assertionCtrl array\n");
545 } else if (gDvm.assertionCtrlCount != 0) {
546 LOGD("Not late-enabling assertions: some asserts already configured\n");
549 LOGD("Late-enabling assertions\n");
551 /* global enable for all but system */
552 AssertionControl* pCtrl = gDvm.assertionCtrl;
553 pCtrl->pkgOrClass = strdup("");
554 pCtrl->pkgOrClassLen = 0;
555 pCtrl->isPackage = false;
556 pCtrl->enable = true;
557 gDvm.assertionCtrlCount = 1;
562 * Release memory associated with the AssertionCtrl array.
564 static void freeAssertionCtrl(void)
568 for (i = 0; i < gDvm.assertionCtrlCount; i++)
569 free(gDvm.assertionCtrl[i].pkgOrClass);
570 free(gDvm.assertionCtrl);
573 #if defined(WITH_JIT)
574 /* Parse -Xjitop to selectively turn on/off certain opcodes for JIT */
575 static void processXjitop(const char *opt)
578 const char *startPtr = &opt[8];
582 long startValue, endValue;
584 startValue = strtol(startPtr, &endPtr, 16);
585 if (startPtr != endPtr) {
586 /* Just in case value is out of range */
589 if (*endPtr == '-') {
590 endValue = strtol(endPtr+1, &endPtr, 16);
593 endValue = startValue;
596 for (; startValue <= endValue; startValue++) {
597 LOGW("Dalvik opcode %x is selected for debugging",
598 (unsigned int) startValue);
599 /* Mark the corresponding bit to 1 */
600 gDvmJit.opList[startValue >> 3] |=
601 1 << (startValue & 0x7);
608 startPtr = endPtr + 1;
614 "Warning: Unrecognized opcode value substring "
622 for (i = 0; i < 32; i++) {
623 gDvmJit.opList[i] = 0xff;
625 dvmFprintf(stderr, "Warning: select all opcodes\n");
629 /* Parse -Xjitmethod to selectively turn on/off certain methods for JIT */
630 static void processXjitmethod(const char *opt)
632 char *buf = strdup(&opt[12]);
635 gDvmJit.methodTable = dvmHashTableCreate(8, NULL);
639 * Break comma-separated method signatures and enter them into the hash
640 * table individually.
645 end = strchr(start, ',');
650 hashValue = dvmComputeUtf8Hash(start);
652 dvmHashTableLookup(gDvmJit.methodTable, hashValue,
654 (HashCompareFunc) strcmp, true);
666 * Process an argument vector full of options. Unlike standard C programs,
667 * argv[0] does not contain the name of the program.
669 * If "ignoreUnrecognized" is set, we ignore options starting with "-X" or "_"
670 * that we don't recognize. Otherwise, we return with an error as soon as
671 * we see anything we can't identify.
673 * Returns 0 on success, -1 on failure, and 1 for the special case of
674 * "-version" where we want to stop without showing an error message.
676 static int dvmProcessOptions(int argc, const char* const argv[],
677 bool ignoreUnrecognized)
681 LOGV("VM options (%d):\n", argc);
682 for (i = 0; i < argc; i++)
683 LOGV(" %d: '%s'\n", i, argv[i]);
686 * Over-allocate AssertionControl array for convenience. If allocated,
687 * the array must be able to hold at least one entry, so that the
688 * zygote-time activation can do its business.
690 assert(gDvm.assertionCtrl == NULL);
693 (AssertionControl*) malloc(sizeof(AssertionControl) * argc);
694 if (gDvm.assertionCtrl == NULL)
696 assert(gDvm.assertionCtrlCount == 0);
699 for (i = 0; i < argc; i++) {
700 if (strcmp(argv[i], "-help") == 0) {
701 /* show usage and stop */
704 } else if (strcmp(argv[i], "-version") == 0) {
705 /* show version and stop */
708 } else if (strcmp(argv[i], "-showversion") == 0) {
709 /* show version and continue */
712 } else if (strcmp(argv[i], "-classpath") == 0 ||
713 strcmp(argv[i], "-cp") == 0)
717 dvmFprintf(stderr, "Missing classpath path list\n");
720 free(gDvm.classPathStr); /* in case we have compiled-in default */
721 gDvm.classPathStr = strdup(argv[++i]);
723 } else if (strncmp(argv[i], "-Xbootclasspath:",
724 sizeof("-Xbootclasspath:")-1) == 0)
726 /* set bootclasspath */
727 const char* path = argv[i] + sizeof("-Xbootclasspath:")-1;
730 dvmFprintf(stderr, "Missing bootclasspath path list\n");
733 free(gDvm.bootClassPathStr);
734 gDvm.bootClassPathStr = strdup(path);
737 * TODO: support -Xbootclasspath/a and /p, which append or
738 * prepend to the default bootclasspath. We set the default
742 } else if (strncmp(argv[i], "-D", 2) == 0) {
744 dvmAddCommandLineProperty(argv[i] + 2);
746 } else if (strcmp(argv[i], "-jar") == 0) {
747 // TODO: handle this; name of jar should be in argv[i+1]
748 dvmFprintf(stderr, "-jar not yet handled\n");
751 } else if (strncmp(argv[i], "-Xms", 4) == 0) {
752 unsigned int val = dvmParseMemOption(argv[i]+4, 1024);
754 if (val >= kMinHeapStartSize && val <= kMaxHeapSize) {
755 gDvm.heapSizeStart = val;
758 "Invalid -Xms '%s', range is %dKB to %dKB\n",
759 argv[i], kMinHeapStartSize/1024, kMaxHeapSize/1024);
763 dvmFprintf(stderr, "Invalid -Xms option '%s'\n", argv[i]);
766 } else if (strncmp(argv[i], "-Xmx", 4) == 0) {
767 unsigned int val = dvmParseMemOption(argv[i]+4, 1024);
769 if (val >= kMinHeapSize && val <= kMaxHeapSize) {
770 gDvm.heapSizeMax = val;
773 "Invalid -Xmx '%s', range is %dKB to %dKB\n",
774 argv[i], kMinHeapSize/1024, kMaxHeapSize/1024);
778 dvmFprintf(stderr, "Invalid -Xmx option '%s'\n", argv[i]);
781 } else if (strncmp(argv[i], "-Xss", 4) == 0) {
782 unsigned int val = dvmParseMemOption(argv[i]+4, 1);
784 if (val >= kMinStackSize && val <= kMaxStackSize) {
785 gDvm.stackSize = val;
787 dvmFprintf(stderr, "Invalid -Xss '%s', range is %d to %d\n",
788 argv[i], kMinStackSize, kMaxStackSize);
792 dvmFprintf(stderr, "Invalid -Xss option '%s'\n", argv[i]);
796 } else if (strcmp(argv[i], "-verbose") == 0 ||
797 strcmp(argv[i], "-verbose:class") == 0)
799 // JNI spec says "-verbose:gc,class" is valid, but cmd line
800 // doesn't work that way; may want to support.
801 gDvm.verboseClass = true;
802 } else if (strcmp(argv[i], "-verbose:jni") == 0) {
803 gDvm.verboseJni = true;
804 } else if (strcmp(argv[i], "-verbose:gc") == 0) {
805 gDvm.verboseGc = true;
806 } else if (strcmp(argv[i], "-verbose:shutdown") == 0) {
807 gDvm.verboseShutdown = true;
809 } else if (strncmp(argv[i], "-enableassertions", 17) == 0) {
810 enableAssertions(argv[i] + 17, true);
811 } else if (strncmp(argv[i], "-ea", 3) == 0) {
812 enableAssertions(argv[i] + 3, true);
813 } else if (strncmp(argv[i], "-disableassertions", 18) == 0) {
814 enableAssertions(argv[i] + 18, false);
815 } else if (strncmp(argv[i], "-da", 3) == 0) {
816 enableAssertions(argv[i] + 3, false);
817 } else if (strcmp(argv[i], "-enablesystemassertions") == 0 ||
818 strcmp(argv[i], "-esa") == 0)
820 enableAssertions(NULL, true);
821 } else if (strcmp(argv[i], "-disablesystemassertions") == 0 ||
822 strcmp(argv[i], "-dsa") == 0)
824 enableAssertions(NULL, false);
826 } else if (strncmp(argv[i], "-Xcheck:jni", 11) == 0) {
827 /* nothing to do now -- was handled during JNI init */
829 } else if (strcmp(argv[i], "-Xdebug") == 0) {
830 /* accept but ignore */
832 } else if (strncmp(argv[i], "-Xrunjdwp:", 10) == 0 ||
833 strncmp(argv[i], "-agentlib:jdwp=", 15) == 0)
837 if (argv[i][1] == 'X')
842 if (strncmp(tail, "help", 4) == 0 || !parseJdwpOptions(tail)) {
846 } else if (strcmp(argv[i], "-Xrs") == 0) {
847 gDvm.reduceSignals = true;
848 } else if (strcmp(argv[i], "-Xnoquithandler") == 0) {
849 /* disables SIGQUIT handler thread while still blocking SIGQUIT */
850 /* (useful if we don't want thread but system still signals us) */
851 gDvm.noQuitHandler = true;
852 } else if (strcmp(argv[i], "-Xzygote") == 0) {
854 #if defined(WITH_JIT)
855 gDvmJit.runningInAndroidFramework = true;
857 } else if (strncmp(argv[i], "-Xdexopt:", 9) == 0) {
858 if (strcmp(argv[i] + 9, "none") == 0)
859 gDvm.dexOptMode = OPTIMIZE_MODE_NONE;
860 else if (strcmp(argv[i] + 9, "verified") == 0)
861 gDvm.dexOptMode = OPTIMIZE_MODE_VERIFIED;
862 else if (strcmp(argv[i] + 9, "all") == 0)
863 gDvm.dexOptMode = OPTIMIZE_MODE_ALL;
865 dvmFprintf(stderr, "Unrecognized dexopt option '%s'\n",argv[i]);
868 } else if (strncmp(argv[i], "-Xverify:", 9) == 0) {
869 if (strcmp(argv[i] + 9, "none") == 0)
870 gDvm.classVerifyMode = VERIFY_MODE_NONE;
871 else if (strcmp(argv[i] + 9, "remote") == 0)
872 gDvm.classVerifyMode = VERIFY_MODE_REMOTE;
873 else if (strcmp(argv[i] + 9, "all") == 0)
874 gDvm.classVerifyMode = VERIFY_MODE_ALL;
876 dvmFprintf(stderr, "Unrecognized verify option '%s'\n",argv[i]);
879 } else if (strncmp(argv[i], "-Xjnigreflimit:", 15) == 0) {
880 int lim = atoi(argv[i] + 15);
881 if (lim < 200 || (lim % 100) != 0) {
882 dvmFprintf(stderr, "Bad value for -Xjnigreflimit: '%s'\n",
886 gDvm.jniGrefLimit = lim;
887 } else if (strncmp(argv[i], "-Xjnitrace:", 11) == 0) {
888 gDvm.jniTrace = strdup(argv[i] + 11);
889 } else if (strcmp(argv[i], "-Xlog-stdio") == 0) {
890 gDvm.logStdio = true;
892 } else if (strncmp(argv[i], "-Xint", 5) == 0) {
893 if (argv[i][5] == ':') {
894 if (strcmp(argv[i] + 6, "portable") == 0)
895 gDvm.executionMode = kExecutionModeInterpPortable;
896 else if (strcmp(argv[i] + 6, "fast") == 0)
897 gDvm.executionMode = kExecutionModeInterpFast;
899 else if (strcmp(argv[i] + 6, "jit") == 0)
900 gDvm.executionMode = kExecutionModeJit;
904 "Warning: Unrecognized interpreter mode %s\n",argv[i]);
908 /* disable JIT if it was enabled by default */
909 gDvm.executionMode = kExecutionModeInterpFast;
912 } else if (strncmp(argv[i], "-Xlockprofthreshold:", 20) == 0) {
913 gDvm.lockProfThreshold = atoi(argv[i] + 20);
916 } else if (strncmp(argv[i], "-Xjitop", 7) == 0) {
917 processXjitop(argv[i]);
918 } else if (strncmp(argv[i], "-Xjitmethod", 11) == 0) {
919 processXjitmethod(argv[i]);
920 } else if (strncmp(argv[i], "-Xjitblocking", 13) == 0) {
921 gDvmJit.blockingMode = true;
922 } else if (strncmp(argv[i], "-Xjitthreshold:", 15) == 0) {
923 gDvmJit.threshold = atoi(argv[i] + 15);
924 } else if (strncmp(argv[i], "-Xincludeselectedop", 19) == 0) {
925 gDvmJit.includeSelectedOp = true;
926 } else if (strncmp(argv[i], "-Xincludeselectedmethod", 23) == 0) {
927 gDvmJit.includeSelectedMethod = true;
928 } else if (strncmp(argv[i], "-Xjitcheckcg", 12) == 0) {
929 gDvmJit.checkCallGraph = true;
930 /* Need to enable blocking mode due to stack crawling */
931 gDvmJit.blockingMode = true;
932 } else if (strncmp(argv[i], "-Xjitverbose", 12) == 0) {
933 gDvmJit.printMe = true;
934 } else if (strncmp(argv[i], "-Xjitprofile", 12) == 0) {
935 gDvmJit.profile = true;
936 } else if (strncmp(argv[i], "-Xjitdisableopt", 15) == 0) {
937 /* Disable selected optimizations */
938 if (argv[i][15] == ':') {
939 sscanf(argv[i] + 16, "%x", &gDvmJit.disableOpt);
940 /* Disable all optimizations */
942 gDvmJit.disableOpt = -1;
946 } else if (strncmp(argv[i], "-Xdeadlockpredict:", 18) == 0) {
947 #ifdef WITH_DEADLOCK_PREDICTION
948 if (strcmp(argv[i] + 18, "off") == 0)
949 gDvm.deadlockPredictMode = kDPOff;
950 else if (strcmp(argv[i] + 18, "warn") == 0)
951 gDvm.deadlockPredictMode = kDPWarn;
952 else if (strcmp(argv[i] + 18, "err") == 0)
953 gDvm.deadlockPredictMode = kDPErr;
954 else if (strcmp(argv[i] + 18, "abort") == 0)
955 gDvm.deadlockPredictMode = kDPAbort;
957 dvmFprintf(stderr, "Bad value for -Xdeadlockpredict");
960 if (gDvm.deadlockPredictMode != kDPOff)
961 LOGD("Deadlock prediction enabled (%s)\n", argv[i]+18);
964 } else if (strncmp(argv[i], "-Xstacktracefile:", 17) == 0) {
965 gDvm.stackTraceFile = strdup(argv[i]+17);
967 } else if (strcmp(argv[i], "-Xgenregmap") == 0) {
968 gDvm.generateRegisterMaps = true;
969 LOGV("Register maps will be generated during verification\n");
971 } else if (strncmp(argv[i], "-Xgc:", 5) == 0) {
972 if (strcmp(argv[i] + 5, "precise") == 0)
973 gDvm.preciseGc = true;
974 else if (strcmp(argv[i] + 5, "noprecise") == 0)
975 gDvm.preciseGc = false;
976 else if (strcmp(argv[i] + 5, "preverify") == 0)
977 gDvm.preVerify = true;
978 else if (strcmp(argv[i] + 5, "nopreverify") == 0)
979 gDvm.preVerify = false;
980 else if (strcmp(argv[i] + 5, "postverify") == 0)
981 gDvm.postVerify = true;
982 else if (strcmp(argv[i] + 5, "nopostverify") == 0)
983 gDvm.postVerify = false;
984 else if (strcmp(argv[i] + 5, "concurrent") == 0)
985 gDvm.concurrentMarkSweep = true;
986 else if (strcmp(argv[i] + 5, "noconcurrent") == 0)
987 gDvm.concurrentMarkSweep = false;
988 else if (strcmp(argv[i] + 5, "verifycardtable") == 0)
989 gDvm.verifyCardTable = true;
990 else if (strcmp(argv[i] + 5, "noverifycardtable") == 0)
991 gDvm.verifyCardTable = false;
993 dvmFprintf(stderr, "Bad value for -Xgc");
996 LOGV("Precise GC configured %s\n", gDvm.preciseGc ? "ON" : "OFF");
998 } else if (strcmp(argv[i], "-Xcheckdexsum") == 0) {
999 gDvm.verifyDexChecksum = true;
1001 } else if (strcmp(argv[i], "-Xprofile:wallclock") == 0) {
1002 gDvm.profilerWallClock = true;
1005 if (!ignoreUnrecognized) {
1006 dvmFprintf(stderr, "Unrecognized option '%s'\n", argv[i]);
1012 if (gDvm.heapSizeStart > gDvm.heapSizeMax) {
1013 dvmFprintf(stderr, "Heap start size must be <= heap max size\n");
1021 * Set defaults for fields altered or modified by arguments.
1023 * Globals are initialized to 0 (a/k/a NULL or false).
1025 static void setCommandLineDefaults()
1029 envStr = getenv("CLASSPATH");
1031 gDvm.classPathStr = strdup(envStr);
1033 gDvm.classPathStr = strdup(".");
1034 envStr = getenv("BOOTCLASSPATH");
1036 gDvm.bootClassPathStr = strdup(envStr);
1038 gDvm.bootClassPathStr = strdup(".");
1040 /* Defaults overridden by -Xms and -Xmx.
1041 * TODO: base these on a system or application-specific default
1043 gDvm.heapSizeStart = 2 * 1024 * 1024; // Spec says 16MB; too big for us.
1044 gDvm.heapSizeMax = 16 * 1024 * 1024; // Spec says 75% physical mem
1045 gDvm.stackSize = kDefaultStackSize;
1047 gDvm.concurrentMarkSweep = true;
1049 /* gDvm.jdwpSuspend = true; */
1051 /* allowed unless zygote config doesn't allow it */
1052 gDvm.jdwpAllowed = true;
1054 /* default verification and optimization modes */
1055 gDvm.classVerifyMode = VERIFY_MODE_ALL;
1056 gDvm.dexOptMode = OPTIMIZE_MODE_VERIFIED;
1059 * Default execution mode.
1061 * This should probably interact with the mterp code somehow, e.g. if
1062 * we know we're using the "desktop" build we should probably be
1063 * using "portable" rather than "fast".
1065 #if defined(WITH_JIT)
1066 gDvm.executionMode = kExecutionModeJit;
1068 gDvm.executionMode = kExecutionModeInterpFast;
1072 * SMP support is a compile-time define, but we may want to have
1073 * dexopt target a differently-configured device.
1075 gDvm.dexOptForSmp = (ANDROID_SMP != 0);
1080 * Handle a SIGBUS, which frequently occurs because somebody replaced an
1081 * optimized DEX file out from under us.
1083 static void busCatcher(int signum, siginfo_t* info, void* context)
1085 void* addr = info->si_addr;
1087 LOGE("Caught a SIGBUS (%d), addr=%p\n", signum, addr);
1090 * If we return at this point the SIGBUS just keeps happening, so we
1091 * remove the signal handler and allow it to kill us. TODO: restore
1092 * the original, which points to a debuggerd stub; if we don't then
1093 * debuggerd won't be notified.
1095 signal(SIGBUS, SIG_DFL);
1099 * Configure signals. We need to block SIGQUIT so that the signal only
1100 * reaches the dump-stack-trace thread.
1102 * This can be disabled with the "-Xrs" flag.
1104 static void blockSignals()
1110 sigaddset(&mask, SIGQUIT);
1111 sigaddset(&mask, SIGUSR1); // used to initiate heap dump
1112 #if defined(WITH_JIT) && defined(WITH_JIT_TUNING)
1113 sigaddset(&mask, SIGUSR2); // used to investigate JIT internals
1115 //sigaddset(&mask, SIGPIPE);
1116 cc = sigprocmask(SIG_BLOCK, &mask, NULL);
1120 /* TODO: save the old sigaction in a global */
1121 struct sigaction sa;
1122 memset(&sa, 0, sizeof(sa));
1123 sa.sa_sigaction = busCatcher;
1124 sa.sa_flags = SA_SIGINFO;
1125 cc = sigaction(SIGBUS, &sa, NULL);
1131 * VM initialization. Pass in any options provided on the command line.
1132 * Do not pass in the class name or the options for the class.
1134 * Returns 0 on success.
1136 int dvmStartup(int argc, const char* const argv[], bool ignoreUnrecognized,
1141 assert(gDvm.initializing);
1143 LOGV("VM init args (%d):\n", argc);
1144 for (i = 0; i < argc; i++)
1145 LOGV(" %d: '%s'\n", i, argv[i]);
1147 setCommandLineDefaults();
1149 /* prep properties storage */
1150 if (!dvmPropertiesStartup(argc))
1154 * Process the option flags (if any).
1156 cc = dvmProcessOptions(argc, argv, ignoreUnrecognized);
1159 dvmFprintf(stderr, "\n");
1160 dvmUsage("dalvikvm");
1165 #if WITH_EXTRA_GC_CHECKS > 1
1166 /* only "portable" interp has the extra goodies */
1167 if (gDvm.executionMode != kExecutionModeInterpPortable) {
1168 LOGI("Switching to 'portable' interpreter for GC checks\n");
1169 gDvm.executionMode = kExecutionModeInterpPortable;
1173 /* Configure group scheduling capabilities */
1174 if (!access("/dev/cpuctl/tasks", F_OK)) {
1175 LOGV("Using kernel group scheduling");
1176 gDvm.kernelGroupScheduling = 1;
1178 LOGV("Using kernel scheduler policies");
1181 /* configure signal handling */
1182 if (!gDvm.reduceSignals)
1185 /* verify system page size */
1186 if (sysconf(_SC_PAGESIZE) != SYSTEM_PAGE_SIZE) {
1187 LOGE("ERROR: expected page size %d, got %d\n",
1188 SYSTEM_PAGE_SIZE, (int) sysconf(_SC_PAGESIZE));
1193 LOGV("Using executionMode %d\n", gDvm.executionMode);
1194 dvmCheckAsmConstants();
1197 * Initialize components.
1199 if (!dvmAllocTrackerStartup())
1201 if (!dvmGcStartup())
1203 if (!dvmThreadStartup())
1205 if (!dvmInlineNativeStartup())
1207 if (!dvmVerificationStartup())
1209 if (!dvmRegisterMapStartup())
1211 if (!dvmInstanceofStartup())
1213 if (!dvmClassStartup())
1215 if (!dvmThreadObjStartup())
1217 if (!dvmExceptionStartup())
1219 if (!dvmStringInternStartup())
1221 if (!dvmNativeStartup())
1223 if (!dvmInternalNativeStartup())
1225 if (!dvmJniStartup())
1227 if (!dvmReflectStartup())
1229 if (!dvmProfilingStartup())
1232 /* make sure we got these [can this go away?] */
1233 assert(gDvm.classJavaLangClass != NULL);
1234 assert(gDvm.classJavaLangObject != NULL);
1235 //assert(gDvm.classJavaLangString != NULL);
1236 assert(gDvm.classJavaLangThread != NULL);
1237 assert(gDvm.classJavaLangVMThread != NULL);
1238 assert(gDvm.classJavaLangThreadGroup != NULL);
1241 * Make sure these exist. If they don't, we can return a failure out
1242 * of main and nip the whole thing in the bud.
1244 static const char* earlyClasses[] = {
1245 "Ljava/lang/InternalError;",
1246 "Ljava/lang/StackOverflowError;",
1247 "Ljava/lang/UnsatisfiedLinkError;",
1248 "Ljava/lang/NoClassDefFoundError;",
1251 const char** pClassName;
1252 for (pClassName = earlyClasses; *pClassName != NULL; pClassName++) {
1253 if (dvmFindSystemClassNoInit(*pClassName) == NULL)
1258 * Miscellaneous class library validation.
1260 if (!dvmValidateBoxClasses())
1264 * Do the last bits of Thread struct initialization we need to allow
1265 * JNI calls to work.
1267 if (!dvmPrepMainForJni(pEnv))
1271 * Register the system native methods, which are registered through JNI.
1273 if (!registerSystemNatives(pEnv))
1277 * Do some "late" initialization for the memory allocator. This may
1278 * allocate storage and initialize classes.
1280 if (!dvmCreateStockExceptions())
1284 * At this point, the VM is in a pretty good state. Finish prep on
1285 * the main thread (specifically, create a java.lang.Thread object to go
1286 * along with our Thread struct). Note we will probably be executing
1287 * some interpreted class initializer code in here.
1289 if (!dvmPrepMainThread())
1293 * Make sure we haven't accumulated any tracked references. The main
1294 * thread should be starting with a clean slate.
1296 if (dvmReferenceTableEntries(&dvmThreadSelf()->internalLocalRefTable) != 0)
1298 LOGW("Warning: tracked references remain post-initialization\n");
1299 dvmDumpReferenceTable(&dvmThreadSelf()->internalLocalRefTable, "MAIN");
1302 /* general debugging setup */
1303 if (!dvmDebuggerStartup())
1307 * Init for either zygote mode or non-zygote mode. The key difference
1308 * is that we don't start any additional threads in Zygote mode.
1311 if (!dvmInitZygote())
1314 if (!dvmInitAfterZygote())
1321 LOGE("dmvTestHash FAILED\n");
1322 if (false /*noisy!*/ && !dvmTestIndirectRefTable())
1323 LOGE("dvmTestIndirectRefTable FAILED\n");
1326 assert(!dvmCheckException(dvmThreadSelf()));
1327 gDvm.initExceptionCount = 0;
1337 * Register java.* natives from our class libraries. We need to do
1338 * this after we're ready for JNI registration calls, but before we
1339 * do any class initialization.
1341 * If we get this wrong, we will blow up in the ThreadGroup class init if
1342 * interpreted code makes any reference to System. It will likely do this
1343 * since it wants to do some java.io.File setup (e.g. for static in/out/err).
1345 * We need to have gDvm.initializing raised here so that JNI FindClass
1346 * won't try to use the system/application class loader.
1348 static bool registerSystemNatives(JNIEnv* pEnv)
1352 /* main thread is always first in list */
1353 self = gDvm.threadList;
1355 /* must set this before allowing JNI-based method registration */
1356 self->status = THREAD_NATIVE;
1358 if (jniRegisterSystemMethods(pEnv) < 0) {
1359 LOGW("jniRegisterSystemMethods failed\n");
1363 /* back to run mode */
1364 self->status = THREAD_RUNNING;
1371 * Do zygote-mode-only initialization.
1373 static bool dvmInitZygote(void)
1375 /* zygote goes into its own process group */
1382 * Do non-zygote-mode initialization. This is done during VM init for
1383 * standard startup, or after a "zygote fork" when creating a new process.
1385 bool dvmInitAfterZygote(void)
1387 u8 startHeap, startQuit, startJdwp;
1388 u8 endHeap, endQuit, endJdwp;
1390 startHeap = dvmGetRelativeTimeUsec();
1393 * Post-zygote heap initialization, including starting
1394 * the HeapWorker thread.
1396 if (!dvmGcStartupAfterZygote())
1399 endHeap = dvmGetRelativeTimeUsec();
1400 startQuit = dvmGetRelativeTimeUsec();
1402 /* start signal catcher thread that dumps stacks on SIGQUIT */
1403 if (!gDvm.reduceSignals && !gDvm.noQuitHandler) {
1404 if (!dvmSignalCatcherStartup())
1408 /* start stdout/stderr copier, if requested */
1409 if (gDvm.logStdio) {
1410 if (!dvmStdioConverterStartup())
1414 endQuit = dvmGetRelativeTimeUsec();
1415 startJdwp = dvmGetRelativeTimeUsec();
1418 * Start JDWP thread. If the command-line debugger flags specified
1419 * "suspend=y", this will pause the VM. We probably want this to
1422 if (!dvmInitJDWP()) {
1423 LOGD("JDWP init failed; continuing anyway\n");
1426 endJdwp = dvmGetRelativeTimeUsec();
1428 LOGV("thread-start heap=%d quit=%d jdwp=%d total=%d usec\n",
1429 (int)(endHeap-startHeap), (int)(endQuit-startQuit),
1430 (int)(endJdwp-startJdwp), (int)(endJdwp-startHeap));
1433 if (gDvm.executionMode == kExecutionModeJit) {
1434 if (!dvmCompilerStartup())
1443 * Prepare for a connection to a JDWP-compliant debugger.
1445 * Note this needs to happen fairly late in the startup process, because
1446 * we need to have all of the java.* native methods registered (which in
1447 * turn requires JNI to be fully prepped).
1449 * There are several ways to initialize:
1451 * We immediately try to connect to host:port. Bail on failure. On
1452 * success, send VM_START (suspending the VM if "suspend=y").
1453 * server=y suspend=n
1454 * Passively listen for a debugger to connect. Return immediately.
1455 * server=y suspend=y
1456 * Wait until debugger connects. Send VM_START ASAP, suspending the
1457 * VM after the message is sent.
1459 * This gets more complicated with a nonzero value for "timeout".
1461 static bool dvmInitJDWP(void)
1463 assert(!gDvm.zygote);
1466 * Init JDWP if the debugger is enabled. This may connect out to a
1467 * debugger, passively listen for a debugger, or block waiting for a
1470 if (gDvm.jdwpAllowed && gDvm.jdwpConfigured) {
1471 JdwpStartupParams params;
1473 if (gDvm.jdwpHost != NULL) {
1474 if (strlen(gDvm.jdwpHost) >= sizeof(params.host)-1) {
1475 LOGE("ERROR: hostname too long: '%s'\n", gDvm.jdwpHost);
1478 strcpy(params.host, gDvm.jdwpHost);
1480 params.host[0] = '\0';
1482 params.transport = gDvm.jdwpTransport;
1483 params.server = gDvm.jdwpServer;
1484 params.suspend = gDvm.jdwpSuspend;
1485 params.port = gDvm.jdwpPort;
1487 gDvm.jdwpState = dvmJdwpStartup(¶ms);
1488 if (gDvm.jdwpState == NULL) {
1489 LOGW("WARNING: debugger thread failed to initialize\n");
1490 /* TODO: ignore? fail? need to mimic "expected" behavior */
1495 * If a debugger has already attached, send the "welcome" message. This
1496 * may cause us to suspend all threads.
1498 if (dvmJdwpIsActive(gDvm.jdwpState)) {
1499 //dvmChangeStatus(NULL, THREAD_RUNNING);
1500 if (!dvmJdwpPostVMStart(gDvm.jdwpState, gDvm.jdwpSuspend)) {
1501 LOGW("WARNING: failed to post 'start' message to debugger\n");
1504 //dvmChangeStatus(NULL, THREAD_NATIVE);
1511 * An alternative to JNI_CreateJavaVM/dvmStartup that does the first bit
1512 * of initialization and then returns with "initializing" still set. (Used
1513 * by DexOpt command-line utility.)
1515 * Attempting to use JNI or internal natives will fail. It's best if
1516 * no bytecode gets executed, which means no <clinit>, which means no
1517 * exception-throwing. We check the "initializing" flag anyway when
1518 * throwing an exception, so we can insert some code that avoids chucking
1519 * an exception when we're optimizing stuff.
1521 * Returns 0 on success.
1523 int dvmPrepForDexOpt(const char* bootClassPath, DexOptimizerMode dexOptMode,
1524 DexClassVerifyMode verifyMode, int dexoptFlags)
1526 gDvm.initializing = true;
1527 gDvm.optimizing = true;
1529 /* configure signal handling */
1532 /* set some defaults */
1533 setCommandLineDefaults();
1534 free(gDvm.bootClassPathStr);
1535 gDvm.bootClassPathStr = strdup(bootClassPath);
1537 /* set opt/verify modes */
1538 gDvm.dexOptMode = dexOptMode;
1539 gDvm.classVerifyMode = verifyMode;
1540 gDvm.generateRegisterMaps = (dexoptFlags & DEXOPT_GEN_REGISTER_MAPS) != 0;
1543 * Initialize the heap, some basic thread control mutexes, and
1544 * get the bootclasspath prepped.
1546 * We can't load any classes yet because we may not yet have a source
1547 * for things like java.lang.Object and java.lang.Class.
1549 if (!dvmGcStartup())
1551 if (!dvmThreadStartup())
1553 if (!dvmInlineNativeStartup())
1555 if (!dvmVerificationStartup())
1557 if (!dvmRegisterMapStartup())
1559 if (!dvmInstanceofStartup())
1561 if (!dvmClassStartup())
1565 * We leave gDvm.initializing set to "true" so that, if we're not
1566 * able to process the "core" classes, we don't go into a death-spin
1567 * trying to throw a "class not found" exception.
1579 * All threads have stopped. Finish the shutdown procedure.
1581 * We can also be called if startup fails partway through, so be prepared
1582 * to deal with partially initialized data.
1584 * Free any storage allocated in gGlobals.
1586 * We can't dlclose() shared libs we've loaded, because it's possible a
1587 * thread not associated with the VM is running code in one.
1589 * This is called from the JNI DestroyJavaVM function, which can be
1590 * called from any thread. (In practice, this will usually run in the
1591 * same thread that started the VM, a/k/a the main thread, but we don't
1592 * want to assume that.)
1594 void dvmShutdown(void)
1596 LOGV("VM shutting down\n");
1598 if (CALC_CACHE_STATS)
1599 dvmDumpAtomicCacheStats(gDvm.instanceofCache);
1602 * Stop our internal threads.
1604 dvmGcThreadShutdown();
1606 if (gDvm.jdwpState != NULL)
1607 dvmJdwpShutdown(gDvm.jdwpState);
1608 free(gDvm.jdwpHost);
1609 gDvm.jdwpHost = NULL;
1610 free(gDvm.jniTrace);
1611 gDvm.jniTrace = NULL;
1612 free(gDvm.stackTraceFile);
1613 gDvm.stackTraceFile = NULL;
1615 /* tell signal catcher to shut down if it was started */
1616 dvmSignalCatcherShutdown();
1618 /* shut down stdout/stderr conversion */
1619 dvmStdioConverterShutdown();
1622 if (gDvm.executionMode == kExecutionModeJit) {
1623 /* shut down the compiler thread */
1624 dvmCompilerShutdown();
1629 * Kill any daemon threads that still exist. Actively-running threads
1630 * are likely to crash the process if they continue to execute while
1631 * the VM shuts down.
1635 if (gDvm.verboseShutdown)
1636 LOGD("VM cleaning up\n");
1638 dvmDebuggerShutdown();
1639 dvmReflectShutdown();
1640 dvmProfilingShutdown();
1642 dvmStringInternShutdown();
1643 dvmExceptionShutdown();
1644 dvmThreadShutdown();
1646 dvmVerificationShutdown();
1647 dvmRegisterMapShutdown();
1648 dvmInstanceofShutdown();
1649 dvmInlineNativeShutdown();
1651 dvmAllocTrackerShutdown();
1652 dvmPropertiesShutdown();
1654 /* these must happen AFTER dvmClassShutdown has walked through class data */
1655 dvmNativeShutdown();
1656 dvmInternalNativeShutdown();
1658 free(gDvm.bootClassPathStr);
1659 free(gDvm.classPathStr);
1661 freeAssertionCtrl();
1664 * We want valgrind to report anything we forget to free as "definitely
1665 * lost". If there's a pointer in the global chunk, it would be reported
1666 * as "still reachable". Erasing the memory fixes this.
1668 * This must be erased to zero if we want to restart the VM within this
1671 memset(&gDvm, 0xcd, sizeof(gDvm));
1676 * fprintf() wrapper that calls through the JNI-specified vfprintf hook if
1677 * one was specified.
1679 int dvmFprintf(FILE* fp, const char* format, ...)
1684 va_start(args, format);
1685 if (gDvm.vfprintfHook != NULL)
1686 result = (*gDvm.vfprintfHook)(fp, format, args);
1688 result = vfprintf(fp, format, args);
1695 * Abort the VM. We get here on fatal errors. Try very hard not to use
1696 * this; whenever possible, return an error to somebody responsible.
1700 LOGE("VM aborting\n");
1702 fflush(NULL); // flush all open file buffers
1704 /* JNI-supplied abort hook gets right of first refusal */
1705 if (gDvm.abortHook != NULL)
1706 (*gDvm.abortHook)();
1709 * If we call abort(), all threads in the process receives a SIBABRT.
1710 * debuggerd dumps the stack trace of the main thread, whether or not
1711 * that was the thread that failed.
1713 * By stuffing a value into a bogus address, we cause a segmentation
1714 * fault in the current thread, and get a useful log from debuggerd.
1715 * We can also trivially tell the difference between a VM crash and
1716 * a deliberate abort by looking at the fault address.
1718 *((char*)0xdeadd00d) = 38;