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)
201 #ifdef DVM_SHOW_EXCEPTION
202 dvmFprintf(stderr, " show_exception=%d", DVM_SHOW_EXCEPTION);
204 dvmFprintf(stderr, "\n\n");
208 * Show helpful information on JDWP options.
210 static void showJdwpHelp(void)
213 "Example: -Xrunjdwp:transport=dt_socket,address=8000,server=y\n");
215 "Example: -Xrunjdwp:transport=dt_socket,address=localhost:6500,server=n\n");
219 * Show version and copyright info.
221 static void showVersion(void)
223 dvmFprintf(stdout, "DalvikVM version %d.%d.%d\n",
224 DALVIK_MAJOR_VERSION, DALVIK_MINOR_VERSION, DALVIK_BUG_VERSION);
226 "Copyright (C) 2007 The Android Open Source Project\n\n"
227 "This software is built from source code licensed under the "
229 "Version 2.0 (the \"License\"). You may obtain a copy of the "
231 " http://www.apache.org/licenses/LICENSE-2.0\n\n"
232 "See the associated NOTICE file for this software for further "
237 * Parse a string of the form /[0-9]+[kKmMgG]?/, which is used to specify
238 * memory sizes. [kK] indicates kilobytes, [mM] megabytes, and
241 * "s" should point just past the "-Xm?" part of the string.
242 * "min" specifies the lowest acceptable value described by "s".
243 * "div" specifies a divisor, e.g. 1024 if the value must be a multiple
246 * The spec says the -Xmx and -Xms options must be multiples of 1024. It
247 * doesn't say anything about -Xss.
249 * Returns 0 (a useless size) if "s" is malformed or specifies a low or
250 * non-evenly-divisible value.
252 static unsigned int dvmParseMemOption(const char *s, unsigned int div)
254 /* strtoul accepts a leading [+-], which we don't want,
255 * so make sure our string starts with a decimal digit.
261 val = (unsigned int)strtoul(s, (char **)&s2, 10);
263 /* s2 should be pointing just after the number.
264 * If this is the end of the string, the user
265 * has specified a number of bytes. Otherwise,
266 * there should be exactly one more character
267 * that specifies a multiplier.
272 /* The remainder of the string is either a single multiplier
273 * character, or nothing to indicate that the value is in
282 } else if (c == 'k' || c == 'K') {
284 } else if (c == 'm' || c == 'M') {
286 } else if (c == 'g' || c == 'G') {
287 mul = 1024 * 1024 * 1024;
289 /* Unknown multiplier character.
294 if (val <= UINT_MAX / mul) {
297 /* Clamp to a multiple of 1024.
299 val = UINT_MAX & ~(1024-1);
302 /* There's more than one character after the
309 /* The man page says that a -Xm value must be
310 * a multiple of 1024.
312 if (val % div == 0) {
322 * Handle one of the JDWP name/value pairs.
325 * help: if specified, show help message and bail
326 * transport: may be dt_socket or dt_shmem
327 * address: for dt_socket, "host:port", or just "port" when listening
328 * server: if "y", wait for debugger to attach; if "n", attach to debugger
329 * timeout: how long to wait for debugger to connect / listen
331 * Useful with server=n (these aren't supported yet):
332 * onthrow=<exception-name>: connect to debugger when exception thrown
333 * onuncaught=y|n: connect to debugger when uncaught exception thrown
334 * launch=<command-line>: launch the debugger itself
336 * The "transport" option is required, as is "address" if server=n.
338 static bool handleJdwpOption(const char* name, const char* value)
340 if (strcmp(name, "transport") == 0) {
341 if (strcmp(value, "dt_socket") == 0) {
342 gDvm.jdwpTransport = kJdwpTransportSocket;
343 } else if (strcmp(value, "dt_android_adb") == 0) {
344 gDvm.jdwpTransport = kJdwpTransportAndroidAdb;
346 LOGE("JDWP transport '%s' not supported\n", value);
349 } else if (strcmp(name, "server") == 0) {
351 gDvm.jdwpServer = false;
352 else if (*value == 'y')
353 gDvm.jdwpServer = true;
355 LOGE("JDWP option 'server' must be 'y' or 'n'\n");
358 } else if (strcmp(name, "suspend") == 0) {
360 gDvm.jdwpSuspend = false;
361 else if (*value == 'y')
362 gDvm.jdwpSuspend = true;
364 LOGE("JDWP option 'suspend' must be 'y' or 'n'\n");
367 } else if (strcmp(name, "address") == 0) {
368 /* this is either <port> or <host>:<port> */
369 const char* colon = strchr(value, ':');
375 gDvm.jdwpHost = (char*) malloc(colon - value +1);
376 strncpy(gDvm.jdwpHost, value, colon - value +1);
377 gDvm.jdwpHost[colon-value] = '\0';
380 if (*value == '\0') {
381 LOGE("JDWP address missing port\n");
384 port = strtol(value, &end, 10);
386 LOGE("JDWP address has junk in port field '%s'\n", value);
389 gDvm.jdwpPort = port;
390 } else if (strcmp(name, "launch") == 0 ||
391 strcmp(name, "onthrow") == 0 ||
392 strcmp(name, "oncaught") == 0 ||
393 strcmp(name, "timeout") == 0)
395 /* valid but unsupported */
396 LOGI("Ignoring JDWP option '%s'='%s'\n", name, value);
398 LOGI("Ignoring unrecognized JDWP option '%s'='%s'\n", name, value);
405 * Parse the latter half of a -Xrunjdwp/-agentlib:jdwp= string, e.g.:
406 * "transport=dt_socket,address=8000,server=y,suspend=n"
408 static bool parseJdwpOptions(const char* str)
410 char* mangle = strdup(str);
415 * Process all of the name=value pairs.
421 value = strchr(name, '=');
423 LOGE("JDWP opts: garbage at '%s'\n", name);
427 comma = strchr(name, ','); // use name, not value, for safety
430 LOGE("JDWP opts: found comma before '=' in '%s'\n", mangle);
436 *value++ = '\0'; // stomp the '='
438 if (!handleJdwpOption(name, value))
449 * Make sure the combination of arguments makes sense.
451 if (gDvm.jdwpTransport == kJdwpTransportUnknown) {
452 LOGE("JDWP opts: must specify transport\n");
455 if (!gDvm.jdwpServer && (gDvm.jdwpHost == NULL || gDvm.jdwpPort == 0)) {
456 LOGE("JDWP opts: when server=n, must specify host and port\n");
459 // transport mandatory
460 // outbound server address
462 gDvm.jdwpConfigured = true;
471 * Handle one of the four kinds of assertion arguments.
473 * "pkgOrClass" is the last part of an enable/disable line. For a package
474 * the arg looks like "-ea:com.google.fubar...", for a class it looks
475 * like "-ea:com.google.fubar.Wahoo". The string we get starts at the ':'.
477 * For system assertions (-esa/-dsa), "pkgOrClass" is NULL.
479 * Multiple instances of these arguments can be specified, e.g. you can
480 * enable assertions for a package and then disable them for one class in
483 static bool enableAssertions(const char* pkgOrClass, bool enable)
485 AssertionControl* pCtrl = &gDvm.assertionCtrl[gDvm.assertionCtrlCount++];
486 pCtrl->enable = enable;
488 if (pkgOrClass == NULL) {
489 /* enable or disable for all system classes */
490 pCtrl->isPackage = false;
491 pCtrl->pkgOrClass = NULL;
492 pCtrl->pkgOrClassLen = 0;
494 if (*pkgOrClass == '\0') {
495 /* global enable/disable for all but system */
496 pCtrl->isPackage = false;
497 pCtrl->pkgOrClass = strdup("");
498 pCtrl->pkgOrClassLen = 0;
500 pCtrl->pkgOrClass = dvmDotToSlash(pkgOrClass+1); // skip ':'
501 if (pCtrl->pkgOrClass == NULL) {
502 /* can happen if class name includes an illegal '/' */
503 LOGW("Unable to process assertion arg '%s'\n", pkgOrClass);
507 int len = strlen(pCtrl->pkgOrClass);
508 if (len >= 3 && strcmp(pCtrl->pkgOrClass + len-3, "///") == 0) {
509 /* mark as package, truncate two of the three slashes */
510 pCtrl->isPackage = true;
511 *(pCtrl->pkgOrClass + len-2) = '\0';
512 pCtrl->pkgOrClassLen = len - 2;
515 pCtrl->isPackage = false;
516 pCtrl->pkgOrClassLen = len;
525 * Turn assertions on when requested to do so by the Zygote.
527 * This is a bit sketchy. We can't (easily) go back and fiddle with all
528 * of the classes that have already been initialized, so this only
529 * affects classes that have yet to be loaded. If some or all assertions
530 * have been enabled through some other means, we don't want to mess with
531 * it here, so we do nothing. Finally, we assume that there's room in
532 * "assertionCtrl" to hold at least one entry; this is guaranteed by the
535 * This must only be called from the main thread during zygote init.
537 void dvmLateEnableAssertions(void)
539 if (gDvm.assertionCtrl == NULL) {
540 LOGD("Not late-enabling assertions: no assertionCtrl array\n");
542 } else if (gDvm.assertionCtrlCount != 0) {
543 LOGD("Not late-enabling assertions: some asserts already configured\n");
546 LOGD("Late-enabling assertions\n");
548 /* global enable for all but system */
549 AssertionControl* pCtrl = gDvm.assertionCtrl;
550 pCtrl->pkgOrClass = strdup("");
551 pCtrl->pkgOrClassLen = 0;
552 pCtrl->isPackage = false;
553 pCtrl->enable = true;
554 gDvm.assertionCtrlCount = 1;
559 * Release memory associated with the AssertionCtrl array.
561 static void freeAssertionCtrl(void)
565 for (i = 0; i < gDvm.assertionCtrlCount; i++)
566 free(gDvm.assertionCtrl[i].pkgOrClass);
567 free(gDvm.assertionCtrl);
570 #if defined(WITH_JIT)
571 /* Parse -Xjitop to selectively turn on/off certain opcodes for JIT */
572 static void processXjitop(const char *opt)
575 const char *startPtr = &opt[8];
579 long startValue, endValue;
581 startValue = strtol(startPtr, &endPtr, 16);
582 if (startPtr != endPtr) {
583 /* Just in case value is out of range */
586 if (*endPtr == '-') {
587 endValue = strtol(endPtr+1, &endPtr, 16);
590 endValue = startValue;
593 for (; startValue <= endValue; startValue++) {
594 LOGW("Dalvik opcode %x is selected for debugging",
595 (unsigned int) startValue);
596 /* Mark the corresponding bit to 1 */
597 gDvmJit.opList[startValue >> 3] |=
598 1 << (startValue & 0x7);
605 startPtr = endPtr + 1;
611 "Warning: Unrecognized opcode value substring "
619 for (i = 0; i < 32; i++) {
620 gDvmJit.opList[i] = 0xff;
622 dvmFprintf(stderr, "Warning: select all opcodes\n");
626 /* Parse -Xjitmethod to selectively turn on/off certain methods for JIT */
627 static void processXjitmethod(const char *opt)
629 char *buf = strdup(&opt[12]);
632 gDvmJit.methodTable = dvmHashTableCreate(8, NULL);
636 * Break comma-separated method signatures and enter them into the hash
637 * table individually.
642 end = strchr(start, ',');
647 hashValue = dvmComputeUtf8Hash(start);
649 dvmHashTableLookup(gDvmJit.methodTable, hashValue,
651 (HashCompareFunc) strcmp, true);
663 * Process an argument vector full of options. Unlike standard C programs,
664 * argv[0] does not contain the name of the program.
666 * If "ignoreUnrecognized" is set, we ignore options starting with "-X" or "_"
667 * that we don't recognize. Otherwise, we return with an error as soon as
668 * we see anything we can't identify.
670 * Returns 0 on success, -1 on failure, and 1 for the special case of
671 * "-version" where we want to stop without showing an error message.
673 static int dvmProcessOptions(int argc, const char* const argv[],
674 bool ignoreUnrecognized)
678 LOGV("VM options (%d):\n", argc);
679 for (i = 0; i < argc; i++)
680 LOGV(" %d: '%s'\n", i, argv[i]);
683 * Over-allocate AssertionControl array for convenience. If allocated,
684 * the array must be able to hold at least one entry, so that the
685 * zygote-time activation can do its business.
687 assert(gDvm.assertionCtrl == NULL);
690 (AssertionControl*) malloc(sizeof(AssertionControl) * argc);
691 if (gDvm.assertionCtrl == NULL)
693 assert(gDvm.assertionCtrlCount == 0);
696 for (i = 0; i < argc; i++) {
697 if (strcmp(argv[i], "-help") == 0) {
698 /* show usage and stop */
701 } else if (strcmp(argv[i], "-version") == 0) {
702 /* show version and stop */
705 } else if (strcmp(argv[i], "-showversion") == 0) {
706 /* show version and continue */
709 } else if (strcmp(argv[i], "-classpath") == 0 ||
710 strcmp(argv[i], "-cp") == 0)
714 dvmFprintf(stderr, "Missing classpath path list\n");
717 free(gDvm.classPathStr); /* in case we have compiled-in default */
718 gDvm.classPathStr = strdup(argv[++i]);
720 } else if (strncmp(argv[i], "-Xbootclasspath:",
721 sizeof("-Xbootclasspath:")-1) == 0)
723 /* set bootclasspath */
724 const char* path = argv[i] + sizeof("-Xbootclasspath:")-1;
727 dvmFprintf(stderr, "Missing bootclasspath path list\n");
730 free(gDvm.bootClassPathStr);
731 gDvm.bootClassPathStr = strdup(path);
734 * TODO: support -Xbootclasspath/a and /p, which append or
735 * prepend to the default bootclasspath. We set the default
739 } else if (strncmp(argv[i], "-D", 2) == 0) {
741 dvmAddCommandLineProperty(argv[i] + 2);
743 } else if (strcmp(argv[i], "-jar") == 0) {
744 // TODO: handle this; name of jar should be in argv[i+1]
745 dvmFprintf(stderr, "-jar not yet handled\n");
748 } else if (strncmp(argv[i], "-Xms", 4) == 0) {
749 unsigned int val = dvmParseMemOption(argv[i]+4, 1024);
751 if (val >= kMinHeapStartSize && val <= kMaxHeapSize) {
752 gDvm.heapSizeStart = val;
755 "Invalid -Xms '%s', range is %dKB to %dKB\n",
756 argv[i], kMinHeapStartSize/1024, kMaxHeapSize/1024);
760 dvmFprintf(stderr, "Invalid -Xms option '%s'\n", argv[i]);
763 } else if (strncmp(argv[i], "-Xmx", 4) == 0) {
764 unsigned int val = dvmParseMemOption(argv[i]+4, 1024);
766 if (val >= kMinHeapSize && val <= kMaxHeapSize) {
767 gDvm.heapSizeMax = val;
770 "Invalid -Xmx '%s', range is %dKB to %dKB\n",
771 argv[i], kMinHeapSize/1024, kMaxHeapSize/1024);
775 dvmFprintf(stderr, "Invalid -Xmx option '%s'\n", argv[i]);
778 } else if (strncmp(argv[i], "-Xss", 4) == 0) {
779 unsigned int val = dvmParseMemOption(argv[i]+4, 1);
781 if (val >= kMinStackSize && val <= kMaxStackSize) {
782 gDvm.stackSize = val;
784 dvmFprintf(stderr, "Invalid -Xss '%s', range is %d to %d\n",
785 argv[i], kMinStackSize, kMaxStackSize);
789 dvmFprintf(stderr, "Invalid -Xss option '%s'\n", argv[i]);
793 } else if (strcmp(argv[i], "-verbose") == 0 ||
794 strcmp(argv[i], "-verbose:class") == 0)
796 // JNI spec says "-verbose:gc,class" is valid, but cmd line
797 // doesn't work that way; may want to support.
798 gDvm.verboseClass = true;
799 } else if (strcmp(argv[i], "-verbose:jni") == 0) {
800 gDvm.verboseJni = true;
801 } else if (strcmp(argv[i], "-verbose:gc") == 0) {
802 gDvm.verboseGc = true;
803 } else if (strcmp(argv[i], "-verbose:shutdown") == 0) {
804 gDvm.verboseShutdown = true;
806 } else if (strncmp(argv[i], "-enableassertions", 17) == 0) {
807 enableAssertions(argv[i] + 17, true);
808 } else if (strncmp(argv[i], "-ea", 3) == 0) {
809 enableAssertions(argv[i] + 3, true);
810 } else if (strncmp(argv[i], "-disableassertions", 18) == 0) {
811 enableAssertions(argv[i] + 18, false);
812 } else if (strncmp(argv[i], "-da", 3) == 0) {
813 enableAssertions(argv[i] + 3, false);
814 } else if (strcmp(argv[i], "-enablesystemassertions") == 0 ||
815 strcmp(argv[i], "-esa") == 0)
817 enableAssertions(NULL, true);
818 } else if (strcmp(argv[i], "-disablesystemassertions") == 0 ||
819 strcmp(argv[i], "-dsa") == 0)
821 enableAssertions(NULL, false);
823 } else if (strncmp(argv[i], "-Xcheck:jni", 11) == 0) {
824 /* nothing to do now -- was handled during JNI init */
826 } else if (strcmp(argv[i], "-Xdebug") == 0) {
827 /* accept but ignore */
829 } else if (strncmp(argv[i], "-Xrunjdwp:", 10) == 0 ||
830 strncmp(argv[i], "-agentlib:jdwp=", 15) == 0)
834 if (argv[i][1] == 'X')
839 if (strncmp(tail, "help", 4) == 0 || !parseJdwpOptions(tail)) {
843 } else if (strcmp(argv[i], "-Xrs") == 0) {
844 gDvm.reduceSignals = true;
845 } else if (strcmp(argv[i], "-Xnoquithandler") == 0) {
846 /* disables SIGQUIT handler thread while still blocking SIGQUIT */
847 /* (useful if we don't want thread but system still signals us) */
848 gDvm.noQuitHandler = true;
849 } else if (strcmp(argv[i], "-Xzygote") == 0) {
851 #if defined(WITH_JIT)
852 gDvmJit.runningInAndroidFramework = true;
854 } else if (strncmp(argv[i], "-Xdexopt:", 9) == 0) {
855 if (strcmp(argv[i] + 9, "none") == 0)
856 gDvm.dexOptMode = OPTIMIZE_MODE_NONE;
857 else if (strcmp(argv[i] + 9, "verified") == 0)
858 gDvm.dexOptMode = OPTIMIZE_MODE_VERIFIED;
859 else if (strcmp(argv[i] + 9, "all") == 0)
860 gDvm.dexOptMode = OPTIMIZE_MODE_ALL;
862 dvmFprintf(stderr, "Unrecognized dexopt option '%s'\n",argv[i]);
865 } else if (strncmp(argv[i], "-Xverify:", 9) == 0) {
866 if (strcmp(argv[i] + 9, "none") == 0)
867 gDvm.classVerifyMode = VERIFY_MODE_NONE;
868 else if (strcmp(argv[i] + 9, "remote") == 0)
869 gDvm.classVerifyMode = VERIFY_MODE_REMOTE;
870 else if (strcmp(argv[i] + 9, "all") == 0)
871 gDvm.classVerifyMode = VERIFY_MODE_ALL;
873 dvmFprintf(stderr, "Unrecognized verify option '%s'\n",argv[i]);
876 } else if (strncmp(argv[i], "-Xjnigreflimit:", 15) == 0) {
877 int lim = atoi(argv[i] + 15);
878 if (lim < 200 || (lim % 100) != 0) {
879 dvmFprintf(stderr, "Bad value for -Xjnigreflimit: '%s'\n",
883 gDvm.jniGrefLimit = lim;
884 } else if (strncmp(argv[i], "-Xjnitrace:", 11) == 0) {
885 gDvm.jniTrace = strdup(argv[i] + 11);
886 } else if (strcmp(argv[i], "-Xlog-stdio") == 0) {
887 gDvm.logStdio = true;
889 } else if (strncmp(argv[i], "-Xint", 5) == 0) {
890 if (argv[i][5] == ':') {
891 if (strcmp(argv[i] + 6, "portable") == 0)
892 gDvm.executionMode = kExecutionModeInterpPortable;
893 else if (strcmp(argv[i] + 6, "fast") == 0)
894 gDvm.executionMode = kExecutionModeInterpFast;
896 else if (strcmp(argv[i] + 6, "jit") == 0)
897 gDvm.executionMode = kExecutionModeJit;
901 "Warning: Unrecognized interpreter mode %s\n",argv[i]);
905 /* disable JIT if it was enabled by default */
906 gDvm.executionMode = kExecutionModeInterpFast;
909 } else if (strncmp(argv[i], "-Xlockprofthreshold:", 20) == 0) {
910 gDvm.lockProfThreshold = atoi(argv[i] + 20);
913 } else if (strncmp(argv[i], "-Xjitop", 7) == 0) {
914 processXjitop(argv[i]);
915 } else if (strncmp(argv[i], "-Xjitmethod", 11) == 0) {
916 processXjitmethod(argv[i]);
917 } else if (strncmp(argv[i], "-Xjitblocking", 13) == 0) {
918 gDvmJit.blockingMode = true;
919 } else if (strncmp(argv[i], "-Xjitthreshold:", 15) == 0) {
920 gDvmJit.threshold = atoi(argv[i] + 15);
921 } else if (strncmp(argv[i], "-Xincludeselectedop", 19) == 0) {
922 gDvmJit.includeSelectedOp = true;
923 } else if (strncmp(argv[i], "-Xincludeselectedmethod", 23) == 0) {
924 gDvmJit.includeSelectedMethod = true;
925 } else if (strncmp(argv[i], "-Xjitcheckcg", 12) == 0) {
926 gDvmJit.checkCallGraph = true;
927 /* Need to enable blocking mode due to stack crawling */
928 gDvmJit.blockingMode = true;
929 } else if (strncmp(argv[i], "-Xjitverbose", 12) == 0) {
930 gDvmJit.printMe = true;
931 } else if (strncmp(argv[i], "-Xjitprofile", 12) == 0) {
932 gDvmJit.profile = true;
933 } else if (strncmp(argv[i], "-Xjitdisableopt", 15) == 0) {
934 /* Disable selected optimizations */
935 if (argv[i][15] == ':') {
936 sscanf(argv[i] + 16, "%x", &gDvmJit.disableOpt);
937 /* Disable all optimizations */
939 gDvmJit.disableOpt = -1;
943 } else if (strncmp(argv[i], "-Xdeadlockpredict:", 18) == 0) {
944 #ifdef WITH_DEADLOCK_PREDICTION
945 if (strcmp(argv[i] + 18, "off") == 0)
946 gDvm.deadlockPredictMode = kDPOff;
947 else if (strcmp(argv[i] + 18, "warn") == 0)
948 gDvm.deadlockPredictMode = kDPWarn;
949 else if (strcmp(argv[i] + 18, "err") == 0)
950 gDvm.deadlockPredictMode = kDPErr;
951 else if (strcmp(argv[i] + 18, "abort") == 0)
952 gDvm.deadlockPredictMode = kDPAbort;
954 dvmFprintf(stderr, "Bad value for -Xdeadlockpredict");
957 if (gDvm.deadlockPredictMode != kDPOff)
958 LOGD("Deadlock prediction enabled (%s)\n", argv[i]+18);
961 } else if (strncmp(argv[i], "-Xstacktracefile:", 17) == 0) {
962 gDvm.stackTraceFile = strdup(argv[i]+17);
964 } else if (strcmp(argv[i], "-Xgenregmap") == 0) {
965 gDvm.generateRegisterMaps = true;
966 LOGV("Register maps will be generated during verification\n");
968 } else if (strncmp(argv[i], "-Xgc:", 5) == 0) {
969 if (strcmp(argv[i] + 5, "precise") == 0)
970 gDvm.preciseGc = true;
971 else if (strcmp(argv[i] + 5, "noprecise") == 0)
972 gDvm.preciseGc = false;
973 else if (strcmp(argv[i] + 5, "preverify") == 0)
974 gDvm.preVerify = true;
975 else if (strcmp(argv[i] + 5, "nopreverify") == 0)
976 gDvm.preVerify = false;
977 else if (strcmp(argv[i] + 5, "postverify") == 0)
978 gDvm.postVerify = true;
979 else if (strcmp(argv[i] + 5, "nopostverify") == 0)
980 gDvm.postVerify = false;
981 else if (strcmp(argv[i] + 5, "concurrent") == 0)
982 gDvm.concurrentMarkSweep = true;
983 else if (strcmp(argv[i] + 5, "noconcurrent") == 0)
984 gDvm.concurrentMarkSweep = false;
985 else if (strcmp(argv[i] + 5, "verifycardtable") == 0)
986 gDvm.verifyCardTable = true;
987 else if (strcmp(argv[i] + 5, "noverifycardtable") == 0)
988 gDvm.verifyCardTable = false;
990 dvmFprintf(stderr, "Bad value for -Xgc");
993 LOGV("Precise GC configured %s\n", gDvm.preciseGc ? "ON" : "OFF");
995 } else if (strcmp(argv[i], "-Xcheckdexsum") == 0) {
996 gDvm.verifyDexChecksum = true;
998 } else if (strcmp(argv[i], "-Xprofile:wallclock") == 0) {
999 gDvm.profilerWallClock = true;
1002 if (!ignoreUnrecognized) {
1003 dvmFprintf(stderr, "Unrecognized option '%s'\n", argv[i]);
1009 if (gDvm.heapSizeStart > gDvm.heapSizeMax) {
1010 dvmFprintf(stderr, "Heap start size must be <= heap max size\n");
1018 * Set defaults for fields altered or modified by arguments.
1020 * Globals are initialized to 0 (a/k/a NULL or false).
1022 static void setCommandLineDefaults()
1026 envStr = getenv("CLASSPATH");
1028 gDvm.classPathStr = strdup(envStr);
1030 gDvm.classPathStr = strdup(".");
1031 envStr = getenv("BOOTCLASSPATH");
1033 gDvm.bootClassPathStr = strdup(envStr);
1035 gDvm.bootClassPathStr = strdup(".");
1037 /* Defaults overridden by -Xms and -Xmx.
1038 * TODO: base these on a system or application-specific default
1040 gDvm.heapSizeStart = 2 * 1024 * 1024; // Spec says 16MB; too big for us.
1041 gDvm.heapSizeMax = 16 * 1024 * 1024; // Spec says 75% physical mem
1042 gDvm.stackSize = kDefaultStackSize;
1044 gDvm.concurrentMarkSweep = true;
1046 /* gDvm.jdwpSuspend = true; */
1048 /* allowed unless zygote config doesn't allow it */
1049 gDvm.jdwpAllowed = true;
1051 /* default verification and optimization modes */
1052 gDvm.classVerifyMode = VERIFY_MODE_ALL;
1053 gDvm.dexOptMode = OPTIMIZE_MODE_VERIFIED;
1056 * Default execution mode.
1058 * This should probably interact with the mterp code somehow, e.g. if
1059 * we know we're using the "desktop" build we should probably be
1060 * using "portable" rather than "fast".
1062 #if defined(WITH_JIT)
1063 gDvm.executionMode = kExecutionModeJit;
1065 gDvm.executionMode = kExecutionModeInterpFast;
1071 * Handle a SIGBUS, which frequently occurs because somebody replaced an
1072 * optimized DEX file out from under us.
1074 static void busCatcher(int signum, siginfo_t* info, void* context)
1076 void* addr = info->si_addr;
1078 LOGE("Caught a SIGBUS (%d), addr=%p\n", signum, addr);
1081 * If we return at this point the SIGBUS just keeps happening, so we
1082 * remove the signal handler and allow it to kill us. TODO: restore
1083 * the original, which points to a debuggerd stub; if we don't then
1084 * debuggerd won't be notified.
1086 signal(SIGBUS, SIG_DFL);
1090 * Configure signals. We need to block SIGQUIT so that the signal only
1091 * reaches the dump-stack-trace thread.
1093 * This can be disabled with the "-Xrs" flag.
1095 static void blockSignals()
1101 sigaddset(&mask, SIGQUIT);
1102 sigaddset(&mask, SIGUSR1); // used to initiate heap dump
1103 #if defined(WITH_JIT) && defined(WITH_JIT_TUNING)
1104 sigaddset(&mask, SIGUSR2); // used to investigate JIT internals
1106 //sigaddset(&mask, SIGPIPE);
1107 cc = sigprocmask(SIG_BLOCK, &mask, NULL);
1111 /* TODO: save the old sigaction in a global */
1112 struct sigaction sa;
1113 memset(&sa, 0, sizeof(sa));
1114 sa.sa_sigaction = busCatcher;
1115 sa.sa_flags = SA_SIGINFO;
1116 cc = sigaction(SIGBUS, &sa, NULL);
1122 * VM initialization. Pass in any options provided on the command line.
1123 * Do not pass in the class name or the options for the class.
1125 * Returns 0 on success.
1127 int dvmStartup(int argc, const char* const argv[], bool ignoreUnrecognized,
1132 assert(gDvm.initializing);
1134 LOGV("VM init args (%d):\n", argc);
1135 for (i = 0; i < argc; i++)
1136 LOGV(" %d: '%s'\n", i, argv[i]);
1138 setCommandLineDefaults();
1140 /* prep properties storage */
1141 if (!dvmPropertiesStartup(argc))
1145 * Process the option flags (if any).
1147 cc = dvmProcessOptions(argc, argv, ignoreUnrecognized);
1150 dvmFprintf(stderr, "\n");
1151 dvmUsage("dalvikvm");
1156 #if WITH_EXTRA_GC_CHECKS > 1
1157 /* only "portable" interp has the extra goodies */
1158 if (gDvm.executionMode != kExecutionModeInterpPortable) {
1159 LOGI("Switching to 'portable' interpreter for GC checks\n");
1160 gDvm.executionMode = kExecutionModeInterpPortable;
1164 /* Configure group scheduling capabilities */
1165 if (!access("/dev/cpuctl/tasks", F_OK)) {
1166 LOGV("Using kernel group scheduling");
1167 gDvm.kernelGroupScheduling = 1;
1169 LOGV("Using kernel scheduler policies");
1172 /* configure signal handling */
1173 if (!gDvm.reduceSignals)
1176 /* verify system page size */
1177 if (sysconf(_SC_PAGESIZE) != SYSTEM_PAGE_SIZE) {
1178 LOGE("ERROR: expected page size %d, got %d\n",
1179 SYSTEM_PAGE_SIZE, (int) sysconf(_SC_PAGESIZE));
1184 LOGV("Using executionMode %d\n", gDvm.executionMode);
1185 dvmCheckAsmConstants();
1188 * Initialize components.
1190 if (!dvmAllocTrackerStartup())
1192 if (!dvmGcStartup())
1194 if (!dvmThreadStartup())
1196 if (!dvmInlineNativeStartup())
1198 if (!dvmVerificationStartup())
1200 if (!dvmRegisterMapStartup())
1202 if (!dvmInstanceofStartup())
1204 if (!dvmClassStartup())
1206 if (!dvmThreadObjStartup())
1208 if (!dvmExceptionStartup())
1210 if (!dvmStringInternStartup())
1212 if (!dvmNativeStartup())
1214 if (!dvmInternalNativeStartup())
1216 if (!dvmJniStartup())
1218 if (!dvmReflectStartup())
1220 if (!dvmProfilingStartup())
1223 /* make sure we got these [can this go away?] */
1224 assert(gDvm.classJavaLangClass != NULL);
1225 assert(gDvm.classJavaLangObject != NULL);
1226 //assert(gDvm.classJavaLangString != NULL);
1227 assert(gDvm.classJavaLangThread != NULL);
1228 assert(gDvm.classJavaLangVMThread != NULL);
1229 assert(gDvm.classJavaLangThreadGroup != NULL);
1232 * Make sure these exist. If they don't, we can return a failure out
1233 * of main and nip the whole thing in the bud.
1235 static const char* earlyClasses[] = {
1236 "Ljava/lang/InternalError;",
1237 "Ljava/lang/StackOverflowError;",
1238 "Ljava/lang/UnsatisfiedLinkError;",
1239 "Ljava/lang/NoClassDefFoundError;",
1242 const char** pClassName;
1243 for (pClassName = earlyClasses; *pClassName != NULL; pClassName++) {
1244 if (dvmFindSystemClassNoInit(*pClassName) == NULL)
1249 * Miscellaneous class library validation.
1251 if (!dvmValidateBoxClasses())
1255 * Do the last bits of Thread struct initialization we need to allow
1256 * JNI calls to work.
1258 if (!dvmPrepMainForJni(pEnv))
1262 * Register the system native methods, which are registered through JNI.
1264 if (!registerSystemNatives(pEnv))
1268 * Do some "late" initialization for the memory allocator. This may
1269 * allocate storage and initialize classes.
1271 if (!dvmCreateStockExceptions())
1275 * At this point, the VM is in a pretty good state. Finish prep on
1276 * the main thread (specifically, create a java.lang.Thread object to go
1277 * along with our Thread struct). Note we will probably be executing
1278 * some interpreted class initializer code in here.
1280 if (!dvmPrepMainThread())
1284 * Make sure we haven't accumulated any tracked references. The main
1285 * thread should be starting with a clean slate.
1287 if (dvmReferenceTableEntries(&dvmThreadSelf()->internalLocalRefTable) != 0)
1289 LOGW("Warning: tracked references remain post-initialization\n");
1290 dvmDumpReferenceTable(&dvmThreadSelf()->internalLocalRefTable, "MAIN");
1293 /* general debugging setup */
1294 if (!dvmDebuggerStartup())
1298 * Init for either zygote mode or non-zygote mode. The key difference
1299 * is that we don't start any additional threads in Zygote mode.
1302 if (!dvmInitZygote())
1305 if (!dvmInitAfterZygote())
1312 LOGE("dmvTestHash FAILED\n");
1313 if (false /*noisy!*/ && !dvmTestIndirectRefTable())
1314 LOGE("dvmTestIndirectRefTable FAILED\n");
1317 assert(!dvmCheckException(dvmThreadSelf()));
1318 gDvm.initExceptionCount = 0;
1328 * Register java.* natives from our class libraries. We need to do
1329 * this after we're ready for JNI registration calls, but before we
1330 * do any class initialization.
1332 * If we get this wrong, we will blow up in the ThreadGroup class init if
1333 * interpreted code makes any reference to System. It will likely do this
1334 * since it wants to do some java.io.File setup (e.g. for static in/out/err).
1336 * We need to have gDvm.initializing raised here so that JNI FindClass
1337 * won't try to use the system/application class loader.
1339 static bool registerSystemNatives(JNIEnv* pEnv)
1343 /* main thread is always first in list */
1344 self = gDvm.threadList;
1346 /* must set this before allowing JNI-based method registration */
1347 self->status = THREAD_NATIVE;
1349 if (jniRegisterSystemMethods(pEnv) < 0) {
1350 LOGW("jniRegisterSystemMethods failed\n");
1354 /* back to run mode */
1355 self->status = THREAD_RUNNING;
1362 * Do zygote-mode-only initialization.
1364 static bool dvmInitZygote(void)
1366 /* zygote goes into its own process group */
1373 * Do non-zygote-mode initialization. This is done during VM init for
1374 * standard startup, or after a "zygote fork" when creating a new process.
1376 bool dvmInitAfterZygote(void)
1378 u8 startHeap, startQuit, startJdwp;
1379 u8 endHeap, endQuit, endJdwp;
1381 startHeap = dvmGetRelativeTimeUsec();
1384 * Post-zygote heap initialization, including starting
1385 * the HeapWorker thread.
1387 if (!dvmGcStartupAfterZygote())
1390 endHeap = dvmGetRelativeTimeUsec();
1391 startQuit = dvmGetRelativeTimeUsec();
1393 /* start signal catcher thread that dumps stacks on SIGQUIT */
1394 if (!gDvm.reduceSignals && !gDvm.noQuitHandler) {
1395 if (!dvmSignalCatcherStartup())
1399 /* start stdout/stderr copier, if requested */
1400 if (gDvm.logStdio) {
1401 if (!dvmStdioConverterStartup())
1405 endQuit = dvmGetRelativeTimeUsec();
1406 startJdwp = dvmGetRelativeTimeUsec();
1409 * Start JDWP thread. If the command-line debugger flags specified
1410 * "suspend=y", this will pause the VM. We probably want this to
1413 if (!dvmInitJDWP()) {
1414 LOGD("JDWP init failed; continuing anyway\n");
1417 endJdwp = dvmGetRelativeTimeUsec();
1419 LOGV("thread-start heap=%d quit=%d jdwp=%d total=%d usec\n",
1420 (int)(endHeap-startHeap), (int)(endQuit-startQuit),
1421 (int)(endJdwp-startJdwp), (int)(endJdwp-startHeap));
1424 if (gDvm.executionMode == kExecutionModeJit) {
1425 if (!dvmCompilerStartup())
1434 * Prepare for a connection to a JDWP-compliant debugger.
1436 * Note this needs to happen fairly late in the startup process, because
1437 * we need to have all of the java.* native methods registered (which in
1438 * turn requires JNI to be fully prepped).
1440 * There are several ways to initialize:
1442 * We immediately try to connect to host:port. Bail on failure. On
1443 * success, send VM_START (suspending the VM if "suspend=y").
1444 * server=y suspend=n
1445 * Passively listen for a debugger to connect. Return immediately.
1446 * server=y suspend=y
1447 * Wait until debugger connects. Send VM_START ASAP, suspending the
1448 * VM after the message is sent.
1450 * This gets more complicated with a nonzero value for "timeout".
1452 static bool dvmInitJDWP(void)
1454 assert(!gDvm.zygote);
1457 * Init JDWP if the debugger is enabled. This may connect out to a
1458 * debugger, passively listen for a debugger, or block waiting for a
1461 if (gDvm.jdwpAllowed && gDvm.jdwpConfigured) {
1462 JdwpStartupParams params;
1464 if (gDvm.jdwpHost != NULL) {
1465 if (strlen(gDvm.jdwpHost) >= sizeof(params.host)-1) {
1466 LOGE("ERROR: hostname too long: '%s'\n", gDvm.jdwpHost);
1469 strcpy(params.host, gDvm.jdwpHost);
1471 params.host[0] = '\0';
1473 params.transport = gDvm.jdwpTransport;
1474 params.server = gDvm.jdwpServer;
1475 params.suspend = gDvm.jdwpSuspend;
1476 params.port = gDvm.jdwpPort;
1478 gDvm.jdwpState = dvmJdwpStartup(¶ms);
1479 if (gDvm.jdwpState == NULL) {
1480 LOGW("WARNING: debugger thread failed to initialize\n");
1481 /* TODO: ignore? fail? need to mimic "expected" behavior */
1486 * If a debugger has already attached, send the "welcome" message. This
1487 * may cause us to suspend all threads.
1489 if (dvmJdwpIsActive(gDvm.jdwpState)) {
1490 //dvmChangeStatus(NULL, THREAD_RUNNING);
1491 if (!dvmJdwpPostVMStart(gDvm.jdwpState, gDvm.jdwpSuspend)) {
1492 LOGW("WARNING: failed to post 'start' message to debugger\n");
1495 //dvmChangeStatus(NULL, THREAD_NATIVE);
1502 * An alternative to JNI_CreateJavaVM/dvmStartup that does the first bit
1503 * of initialization and then returns with "initializing" still set. (Used
1504 * by DexOpt command-line utility.)
1506 * Attempting to use JNI or internal natives will fail. It's best if
1507 * no bytecode gets executed, which means no <clinit>, which means no
1508 * exception-throwing. We check the "initializing" flag anyway when
1509 * throwing an exception, so we can insert some code that avoids chucking
1510 * an exception when we're optimizing stuff.
1512 * Returns 0 on success.
1514 int dvmPrepForDexOpt(const char* bootClassPath, DexOptimizerMode dexOptMode,
1515 DexClassVerifyMode verifyMode, int dexoptFlags)
1517 gDvm.initializing = true;
1518 gDvm.optimizing = true;
1520 /* configure signal handling */
1523 /* set some defaults */
1524 setCommandLineDefaults();
1525 free(gDvm.bootClassPathStr);
1526 gDvm.bootClassPathStr = strdup(bootClassPath);
1528 /* set opt/verify modes */
1529 gDvm.dexOptMode = dexOptMode;
1530 gDvm.classVerifyMode = verifyMode;
1531 gDvm.generateRegisterMaps = (dexoptFlags & DEXOPT_GEN_REGISTER_MAPS) != 0;
1534 * Initialize the heap, some basic thread control mutexes, and
1535 * get the bootclasspath prepped.
1537 * We can't load any classes yet because we may not yet have a source
1538 * for things like java.lang.Object and java.lang.Class.
1540 if (!dvmGcStartup())
1542 if (!dvmThreadStartup())
1544 if (!dvmInlineNativeStartup())
1546 if (!dvmVerificationStartup())
1548 if (!dvmRegisterMapStartup())
1550 if (!dvmInstanceofStartup())
1552 if (!dvmClassStartup())
1556 * We leave gDvm.initializing set to "true" so that, if we're not
1557 * able to process the "core" classes, we don't go into a death-spin
1558 * trying to throw a "class not found" exception.
1570 * All threads have stopped. Finish the shutdown procedure.
1572 * We can also be called if startup fails partway through, so be prepared
1573 * to deal with partially initialized data.
1575 * Free any storage allocated in gGlobals.
1577 * We can't dlclose() shared libs we've loaded, because it's possible a
1578 * thread not associated with the VM is running code in one.
1580 * This is called from the JNI DestroyJavaVM function, which can be
1581 * called from any thread. (In practice, this will usually run in the
1582 * same thread that started the VM, a/k/a the main thread, but we don't
1583 * want to assume that.)
1585 void dvmShutdown(void)
1587 LOGV("VM shutting down\n");
1589 if (CALC_CACHE_STATS)
1590 dvmDumpAtomicCacheStats(gDvm.instanceofCache);
1593 * Stop our internal threads.
1595 dvmGcThreadShutdown();
1597 if (gDvm.jdwpState != NULL)
1598 dvmJdwpShutdown(gDvm.jdwpState);
1599 free(gDvm.jdwpHost);
1600 gDvm.jdwpHost = NULL;
1601 free(gDvm.jniTrace);
1602 gDvm.jniTrace = NULL;
1603 free(gDvm.stackTraceFile);
1604 gDvm.stackTraceFile = NULL;
1606 /* tell signal catcher to shut down if it was started */
1607 dvmSignalCatcherShutdown();
1609 /* shut down stdout/stderr conversion */
1610 dvmStdioConverterShutdown();
1613 if (gDvm.executionMode == kExecutionModeJit) {
1614 /* shut down the compiler thread */
1615 dvmCompilerShutdown();
1620 * Kill any daemon threads that still exist. Actively-running threads
1621 * are likely to crash the process if they continue to execute while
1622 * the VM shuts down.
1626 if (gDvm.verboseShutdown)
1627 LOGD("VM cleaning up\n");
1629 dvmDebuggerShutdown();
1630 dvmReflectShutdown();
1631 dvmProfilingShutdown();
1633 dvmStringInternShutdown();
1634 dvmExceptionShutdown();
1635 dvmThreadShutdown();
1637 dvmVerificationShutdown();
1638 dvmRegisterMapShutdown();
1639 dvmInstanceofShutdown();
1640 dvmInlineNativeShutdown();
1642 dvmAllocTrackerShutdown();
1643 dvmPropertiesShutdown();
1645 /* these must happen AFTER dvmClassShutdown has walked through class data */
1646 dvmNativeShutdown();
1647 dvmInternalNativeShutdown();
1649 free(gDvm.bootClassPathStr);
1650 free(gDvm.classPathStr);
1652 freeAssertionCtrl();
1655 * We want valgrind to report anything we forget to free as "definitely
1656 * lost". If there's a pointer in the global chunk, it would be reported
1657 * as "still reachable". Erasing the memory fixes this.
1659 * This must be erased to zero if we want to restart the VM within this
1662 memset(&gDvm, 0xcd, sizeof(gDvm));
1667 * fprintf() wrapper that calls through the JNI-specified vfprintf hook if
1668 * one was specified.
1670 int dvmFprintf(FILE* fp, const char* format, ...)
1675 va_start(args, format);
1676 if (gDvm.vfprintfHook != NULL)
1677 result = (*gDvm.vfprintfHook)(fp, format, args);
1679 result = vfprintf(fp, format, args);
1686 * Abort the VM. We get here on fatal errors. Try very hard not to use
1687 * this; whenever possible, return an error to somebody responsible.
1691 LOGE("VM aborting\n");
1693 fflush(NULL); // flush all open file buffers
1695 /* JNI-supplied abort hook gets right of first refusal */
1696 if (gDvm.abortHook != NULL)
1697 (*gDvm.abortHook)();
1700 * If we call abort(), all threads in the process receives a SIBABRT.
1701 * debuggerd dumps the stack trace of the main thread, whether or not
1702 * that was the thread that failed.
1704 * By stuffing a value into a bogus address, we cause a segmentation
1705 * fault in the current thread, and get a useful log from debuggerd.
1706 * We can also trivially tell the difference between a VM crash and
1707 * a deliberate abort by looking at the fault address.
1709 *((char*)0xdeadd00d) = 38;