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 defined(WITH_JIT)
187 #if defined(WITH_SELF_VERIFICATION)
193 #ifdef WITH_INLINE_PROFILING
197 #ifdef DVM_SHOW_EXCEPTION
198 dvmFprintf(stderr, " show_exception=%d", DVM_SHOW_EXCEPTION);
200 dvmFprintf(stderr, "\n\n");
204 * Show helpful information on JDWP options.
206 static void showJdwpHelp(void)
209 "Example: -Xrunjdwp:transport=dt_socket,address=8000,server=y\n");
211 "Example: -Xrunjdwp:transport=dt_socket,address=localhost:6500,server=n\n");
215 * Show version and copyright info.
217 static void showVersion(void)
219 dvmFprintf(stdout, "DalvikVM version %d.%d.%d\n",
220 DALVIK_MAJOR_VERSION, DALVIK_MINOR_VERSION, DALVIK_BUG_VERSION);
222 "Copyright (C) 2007 The Android Open Source Project\n\n"
223 "This software is built from source code licensed under the "
225 "Version 2.0 (the \"License\"). You may obtain a copy of the "
227 " http://www.apache.org/licenses/LICENSE-2.0\n\n"
228 "See the associated NOTICE file for this software for further "
233 * Parse a string of the form /[0-9]+[kKmMgG]?/, which is used to specify
234 * memory sizes. [kK] indicates kilobytes, [mM] megabytes, and
237 * "s" should point just past the "-Xm?" part of the string.
238 * "min" specifies the lowest acceptable value described by "s".
239 * "div" specifies a divisor, e.g. 1024 if the value must be a multiple
242 * The spec says the -Xmx and -Xms options must be multiples of 1024. It
243 * doesn't say anything about -Xss.
245 * Returns 0 (a useless size) if "s" is malformed or specifies a low or
246 * non-evenly-divisible value.
248 static unsigned int dvmParseMemOption(const char *s, unsigned int div)
250 /* strtoul accepts a leading [+-], which we don't want,
251 * so make sure our string starts with a decimal digit.
257 val = (unsigned int)strtoul(s, (char **)&s2, 10);
259 /* s2 should be pointing just after the number.
260 * If this is the end of the string, the user
261 * has specified a number of bytes. Otherwise,
262 * there should be exactly one more character
263 * that specifies a multiplier.
268 /* The remainder of the string is either a single multiplier
269 * character, or nothing to indicate that the value is in
278 } else if (c == 'k' || c == 'K') {
280 } else if (c == 'm' || c == 'M') {
282 } else if (c == 'g' || c == 'G') {
283 mul = 1024 * 1024 * 1024;
285 /* Unknown multiplier character.
290 if (val <= UINT_MAX / mul) {
293 /* Clamp to a multiple of 1024.
295 val = UINT_MAX & ~(1024-1);
298 /* There's more than one character after the
305 /* The man page says that a -Xm value must be
306 * a multiple of 1024.
308 if (val % div == 0) {
318 * Handle one of the JDWP name/value pairs.
321 * help: if specified, show help message and bail
322 * transport: may be dt_socket or dt_shmem
323 * address: for dt_socket, "host:port", or just "port" when listening
324 * server: if "y", wait for debugger to attach; if "n", attach to debugger
325 * timeout: how long to wait for debugger to connect / listen
327 * Useful with server=n (these aren't supported yet):
328 * onthrow=<exception-name>: connect to debugger when exception thrown
329 * onuncaught=y|n: connect to debugger when uncaught exception thrown
330 * launch=<command-line>: launch the debugger itself
332 * The "transport" option is required, as is "address" if server=n.
334 static bool handleJdwpOption(const char* name, const char* value)
336 if (strcmp(name, "transport") == 0) {
337 if (strcmp(value, "dt_socket") == 0) {
338 gDvm.jdwpTransport = kJdwpTransportSocket;
339 } else if (strcmp(value, "dt_android_adb") == 0) {
340 gDvm.jdwpTransport = kJdwpTransportAndroidAdb;
342 LOGE("JDWP transport '%s' not supported\n", value);
345 } else if (strcmp(name, "server") == 0) {
347 gDvm.jdwpServer = false;
348 else if (*value == 'y')
349 gDvm.jdwpServer = true;
351 LOGE("JDWP option 'server' must be 'y' or 'n'\n");
354 } else if (strcmp(name, "suspend") == 0) {
356 gDvm.jdwpSuspend = false;
357 else if (*value == 'y')
358 gDvm.jdwpSuspend = true;
360 LOGE("JDWP option 'suspend' must be 'y' or 'n'\n");
363 } else if (strcmp(name, "address") == 0) {
364 /* this is either <port> or <host>:<port> */
365 const char* colon = strchr(value, ':');
371 gDvm.jdwpHost = (char*) malloc(colon - value +1);
372 strncpy(gDvm.jdwpHost, value, colon - value +1);
373 gDvm.jdwpHost[colon-value] = '\0';
376 if (*value == '\0') {
377 LOGE("JDWP address missing port\n");
380 port = strtol(value, &end, 10);
382 LOGE("JDWP address has junk in port field '%s'\n", value);
385 gDvm.jdwpPort = port;
386 } else if (strcmp(name, "launch") == 0 ||
387 strcmp(name, "onthrow") == 0 ||
388 strcmp(name, "oncaught") == 0 ||
389 strcmp(name, "timeout") == 0)
391 /* valid but unsupported */
392 LOGI("Ignoring JDWP option '%s'='%s'\n", name, value);
394 LOGI("Ignoring unrecognized JDWP option '%s'='%s'\n", name, value);
401 * Parse the latter half of a -Xrunjdwp/-agentlib:jdwp= string, e.g.:
402 * "transport=dt_socket,address=8000,server=y,suspend=n"
404 static bool parseJdwpOptions(const char* str)
406 char* mangle = strdup(str);
411 * Process all of the name=value pairs.
417 value = strchr(name, '=');
419 LOGE("JDWP opts: garbage at '%s'\n", name);
423 comma = strchr(name, ','); // use name, not value, for safety
426 LOGE("JDWP opts: found comma before '=' in '%s'\n", mangle);
432 *value++ = '\0'; // stomp the '='
434 if (!handleJdwpOption(name, value))
445 * Make sure the combination of arguments makes sense.
447 if (gDvm.jdwpTransport == kJdwpTransportUnknown) {
448 LOGE("JDWP opts: must specify transport\n");
451 if (!gDvm.jdwpServer && (gDvm.jdwpHost == NULL || gDvm.jdwpPort == 0)) {
452 LOGE("JDWP opts: when server=n, must specify host and port\n");
455 // transport mandatory
456 // outbound server address
458 gDvm.jdwpConfigured = true;
467 * Handle one of the four kinds of assertion arguments.
469 * "pkgOrClass" is the last part of an enable/disable line. For a package
470 * the arg looks like "-ea:com.google.fubar...", for a class it looks
471 * like "-ea:com.google.fubar.Wahoo". The string we get starts at the ':'.
473 * For system assertions (-esa/-dsa), "pkgOrClass" is NULL.
475 * Multiple instances of these arguments can be specified, e.g. you can
476 * enable assertions for a package and then disable them for one class in
479 static bool enableAssertions(const char* pkgOrClass, bool enable)
481 AssertionControl* pCtrl = &gDvm.assertionCtrl[gDvm.assertionCtrlCount++];
482 pCtrl->enable = enable;
484 if (pkgOrClass == NULL) {
485 /* enable or disable for all system classes */
486 pCtrl->isPackage = false;
487 pCtrl->pkgOrClass = NULL;
488 pCtrl->pkgOrClassLen = 0;
490 if (*pkgOrClass == '\0') {
491 /* global enable/disable for all but system */
492 pCtrl->isPackage = false;
493 pCtrl->pkgOrClass = strdup("");
494 pCtrl->pkgOrClassLen = 0;
496 pCtrl->pkgOrClass = dvmDotToSlash(pkgOrClass+1); // skip ':'
497 if (pCtrl->pkgOrClass == NULL) {
498 /* can happen if class name includes an illegal '/' */
499 LOGW("Unable to process assertion arg '%s'\n", pkgOrClass);
503 int len = strlen(pCtrl->pkgOrClass);
504 if (len >= 3 && strcmp(pCtrl->pkgOrClass + len-3, "///") == 0) {
505 /* mark as package, truncate two of the three slashes */
506 pCtrl->isPackage = true;
507 *(pCtrl->pkgOrClass + len-2) = '\0';
508 pCtrl->pkgOrClassLen = len - 2;
511 pCtrl->isPackage = false;
512 pCtrl->pkgOrClassLen = len;
521 * Turn assertions on when requested to do so by the Zygote.
523 * This is a bit sketchy. We can't (easily) go back and fiddle with all
524 * of the classes that have already been initialized, so this only
525 * affects classes that have yet to be loaded. If some or all assertions
526 * have been enabled through some other means, we don't want to mess with
527 * it here, so we do nothing. Finally, we assume that there's room in
528 * "assertionCtrl" to hold at least one entry; this is guaranteed by the
531 * This must only be called from the main thread during zygote init.
533 void dvmLateEnableAssertions(void)
535 if (gDvm.assertionCtrl == NULL) {
536 LOGD("Not late-enabling assertions: no assertionCtrl array\n");
538 } else if (gDvm.assertionCtrlCount != 0) {
539 LOGD("Not late-enabling assertions: some asserts already configured\n");
542 LOGD("Late-enabling assertions\n");
544 /* global enable for all but system */
545 AssertionControl* pCtrl = gDvm.assertionCtrl;
546 pCtrl->pkgOrClass = strdup("");
547 pCtrl->pkgOrClassLen = 0;
548 pCtrl->isPackage = false;
549 pCtrl->enable = true;
550 gDvm.assertionCtrlCount = 1;
555 * Release memory associated with the AssertionCtrl array.
557 static void freeAssertionCtrl(void)
561 for (i = 0; i < gDvm.assertionCtrlCount; i++)
562 free(gDvm.assertionCtrl[i].pkgOrClass);
563 free(gDvm.assertionCtrl);
566 #if defined(WITH_JIT)
567 /* Parse -Xjitop to selectively turn on/off certain opcodes for JIT */
568 static void processXjitop(const char *opt)
571 const char *startPtr = &opt[8];
575 long startValue, endValue;
577 startValue = strtol(startPtr, &endPtr, 16);
578 if (startPtr != endPtr) {
579 /* Just in case value is out of range */
582 if (*endPtr == '-') {
583 endValue = strtol(endPtr+1, &endPtr, 16);
586 endValue = startValue;
589 for (; startValue <= endValue; startValue++) {
590 LOGW("Dalvik opcode %x is selected for debugging",
591 (unsigned int) startValue);
592 /* Mark the corresponding bit to 1 */
593 gDvmJit.opList[startValue >> 3] |=
594 1 << (startValue & 0x7);
601 startPtr = endPtr + 1;
607 "Warning: Unrecognized opcode value substring "
615 for (i = 0; i < 32; i++) {
616 gDvmJit.opList[i] = 0xff;
618 dvmFprintf(stderr, "Warning: select all opcodes\n");
622 /* Parse -Xjitmethod to selectively turn on/off certain methods for JIT */
623 static void processXjitmethod(const char *opt)
625 char *buf = strdup(&opt[12]);
628 gDvmJit.methodTable = dvmHashTableCreate(8, NULL);
632 * Break comma-separated method signatures and enter them into the hash
633 * table individually.
638 end = strchr(start, ',');
643 hashValue = dvmComputeUtf8Hash(start);
645 dvmHashTableLookup(gDvmJit.methodTable, hashValue,
647 (HashCompareFunc) strcmp, true);
659 * Process an argument vector full of options. Unlike standard C programs,
660 * argv[0] does not contain the name of the program.
662 * If "ignoreUnrecognized" is set, we ignore options starting with "-X" or "_"
663 * that we don't recognize. Otherwise, we return with an error as soon as
664 * we see anything we can't identify.
666 * Returns 0 on success, -1 on failure, and 1 for the special case of
667 * "-version" where we want to stop without showing an error message.
669 static int dvmProcessOptions(int argc, const char* const argv[],
670 bool ignoreUnrecognized)
674 LOGV("VM options (%d):\n", argc);
675 for (i = 0; i < argc; i++)
676 LOGV(" %d: '%s'\n", i, argv[i]);
679 * Over-allocate AssertionControl array for convenience. If allocated,
680 * the array must be able to hold at least one entry, so that the
681 * zygote-time activation can do its business.
683 assert(gDvm.assertionCtrl == NULL);
686 (AssertionControl*) malloc(sizeof(AssertionControl) * argc);
687 if (gDvm.assertionCtrl == NULL)
689 assert(gDvm.assertionCtrlCount == 0);
692 for (i = 0; i < argc; i++) {
693 if (strcmp(argv[i], "-help") == 0) {
694 /* show usage and stop */
697 } else if (strcmp(argv[i], "-version") == 0) {
698 /* show version and stop */
701 } else if (strcmp(argv[i], "-showversion") == 0) {
702 /* show version and continue */
705 } else if (strcmp(argv[i], "-classpath") == 0 ||
706 strcmp(argv[i], "-cp") == 0)
710 dvmFprintf(stderr, "Missing classpath path list\n");
713 free(gDvm.classPathStr); /* in case we have compiled-in default */
714 gDvm.classPathStr = strdup(argv[++i]);
716 } else if (strncmp(argv[i], "-Xbootclasspath:",
717 sizeof("-Xbootclasspath:")-1) == 0)
719 /* set bootclasspath */
720 const char* path = argv[i] + sizeof("-Xbootclasspath:")-1;
723 dvmFprintf(stderr, "Missing bootclasspath path list\n");
726 free(gDvm.bootClassPathStr);
727 gDvm.bootClassPathStr = strdup(path);
730 * TODO: support -Xbootclasspath/a and /p, which append or
731 * prepend to the default bootclasspath. We set the default
735 } else if (strncmp(argv[i], "-D", 2) == 0) {
737 dvmAddCommandLineProperty(argv[i] + 2);
739 } else if (strcmp(argv[i], "-jar") == 0) {
740 // TODO: handle this; name of jar should be in argv[i+1]
741 dvmFprintf(stderr, "-jar not yet handled\n");
744 } else if (strncmp(argv[i], "-Xms", 4) == 0) {
745 unsigned int val = dvmParseMemOption(argv[i]+4, 1024);
747 if (val >= kMinHeapStartSize && val <= kMaxHeapSize) {
748 gDvm.heapSizeStart = val;
751 "Invalid -Xms '%s', range is %dKB to %dKB\n",
752 argv[i], kMinHeapStartSize/1024, kMaxHeapSize/1024);
756 dvmFprintf(stderr, "Invalid -Xms option '%s'\n", argv[i]);
759 } else if (strncmp(argv[i], "-Xmx", 4) == 0) {
760 unsigned int val = dvmParseMemOption(argv[i]+4, 1024);
762 if (val >= kMinHeapSize && val <= kMaxHeapSize) {
763 gDvm.heapSizeMax = val;
766 "Invalid -Xmx '%s', range is %dKB to %dKB\n",
767 argv[i], kMinHeapSize/1024, kMaxHeapSize/1024);
771 dvmFprintf(stderr, "Invalid -Xmx option '%s'\n", argv[i]);
774 } else if (strncmp(argv[i], "-Xss", 4) == 0) {
775 unsigned int val = dvmParseMemOption(argv[i]+4, 1);
777 if (val >= kMinStackSize && val <= kMaxStackSize) {
778 gDvm.stackSize = val;
780 dvmFprintf(stderr, "Invalid -Xss '%s', range is %d to %d\n",
781 argv[i], kMinStackSize, kMaxStackSize);
785 dvmFprintf(stderr, "Invalid -Xss option '%s'\n", argv[i]);
789 } else if (strcmp(argv[i], "-verbose") == 0 ||
790 strcmp(argv[i], "-verbose:class") == 0)
792 // JNI spec says "-verbose:gc,class" is valid, but cmd line
793 // doesn't work that way; may want to support.
794 gDvm.verboseClass = true;
795 } else if (strcmp(argv[i], "-verbose:jni") == 0) {
796 gDvm.verboseJni = true;
797 } else if (strcmp(argv[i], "-verbose:gc") == 0) {
798 gDvm.verboseGc = true;
799 } else if (strcmp(argv[i], "-verbose:shutdown") == 0) {
800 gDvm.verboseShutdown = true;
802 } else if (strncmp(argv[i], "-enableassertions", 17) == 0) {
803 enableAssertions(argv[i] + 17, true);
804 } else if (strncmp(argv[i], "-ea", 3) == 0) {
805 enableAssertions(argv[i] + 3, true);
806 } else if (strncmp(argv[i], "-disableassertions", 18) == 0) {
807 enableAssertions(argv[i] + 18, false);
808 } else if (strncmp(argv[i], "-da", 3) == 0) {
809 enableAssertions(argv[i] + 3, false);
810 } else if (strcmp(argv[i], "-enablesystemassertions") == 0 ||
811 strcmp(argv[i], "-esa") == 0)
813 enableAssertions(NULL, true);
814 } else if (strcmp(argv[i], "-disablesystemassertions") == 0 ||
815 strcmp(argv[i], "-dsa") == 0)
817 enableAssertions(NULL, false);
819 } else if (strncmp(argv[i], "-Xcheck:jni", 11) == 0) {
820 /* nothing to do now -- was handled during JNI init */
822 } else if (strcmp(argv[i], "-Xdebug") == 0) {
823 /* accept but ignore */
825 } else if (strncmp(argv[i], "-Xrunjdwp:", 10) == 0 ||
826 strncmp(argv[i], "-agentlib:jdwp=", 15) == 0)
830 if (argv[i][1] == 'X')
835 if (strncmp(tail, "help", 4) == 0 || !parseJdwpOptions(tail)) {
839 } else if (strcmp(argv[i], "-Xrs") == 0) {
840 gDvm.reduceSignals = true;
841 } else if (strcmp(argv[i], "-Xnoquithandler") == 0) {
842 /* disables SIGQUIT handler thread while still blocking SIGQUIT */
843 /* (useful if we don't want thread but system still signals us) */
844 gDvm.noQuitHandler = true;
845 } else if (strcmp(argv[i], "-Xzygote") == 0) {
847 #if defined(WITH_JIT)
848 gDvmJit.runningInAndroidFramework = true;
850 } else if (strncmp(argv[i], "-Xdexopt:", 9) == 0) {
851 if (strcmp(argv[i] + 9, "none") == 0)
852 gDvm.dexOptMode = OPTIMIZE_MODE_NONE;
853 else if (strcmp(argv[i] + 9, "verified") == 0)
854 gDvm.dexOptMode = OPTIMIZE_MODE_VERIFIED;
855 else if (strcmp(argv[i] + 9, "all") == 0)
856 gDvm.dexOptMode = OPTIMIZE_MODE_ALL;
858 dvmFprintf(stderr, "Unrecognized dexopt option '%s'\n",argv[i]);
861 } else if (strncmp(argv[i], "-Xverify:", 9) == 0) {
862 if (strcmp(argv[i] + 9, "none") == 0)
863 gDvm.classVerifyMode = VERIFY_MODE_NONE;
864 else if (strcmp(argv[i] + 9, "remote") == 0)
865 gDvm.classVerifyMode = VERIFY_MODE_REMOTE;
866 else if (strcmp(argv[i] + 9, "all") == 0)
867 gDvm.classVerifyMode = VERIFY_MODE_ALL;
869 dvmFprintf(stderr, "Unrecognized verify option '%s'\n",argv[i]);
872 } else if (strncmp(argv[i], "-Xjnigreflimit:", 15) == 0) {
873 int lim = atoi(argv[i] + 15);
874 if (lim < 200 || (lim % 100) != 0) {
875 dvmFprintf(stderr, "Bad value for -Xjnigreflimit: '%s'\n",
879 gDvm.jniGrefLimit = lim;
880 } else if (strncmp(argv[i], "-Xjnitrace:", 11) == 0) {
881 gDvm.jniTrace = strdup(argv[i] + 11);
882 } else if (strcmp(argv[i], "-Xlog-stdio") == 0) {
883 gDvm.logStdio = true;
885 } else if (strncmp(argv[i], "-Xint", 5) == 0) {
886 if (argv[i][5] == ':') {
887 if (strcmp(argv[i] + 6, "portable") == 0)
888 gDvm.executionMode = kExecutionModeInterpPortable;
889 else if (strcmp(argv[i] + 6, "fast") == 0)
890 gDvm.executionMode = kExecutionModeInterpFast;
892 else if (strcmp(argv[i] + 6, "jit") == 0)
893 gDvm.executionMode = kExecutionModeJit;
897 "Warning: Unrecognized interpreter mode %s\n",argv[i]);
901 /* disable JIT if it was enabled by default */
902 gDvm.executionMode = kExecutionModeInterpFast;
905 } else if (strncmp(argv[i], "-Xlockprofthreshold:", 20) == 0) {
906 gDvm.lockProfThreshold = atoi(argv[i] + 20);
909 } else if (strncmp(argv[i], "-Xjitop", 7) == 0) {
910 processXjitop(argv[i]);
911 } else if (strncmp(argv[i], "-Xjitmethod", 11) == 0) {
912 processXjitmethod(argv[i]);
913 } else if (strncmp(argv[i], "-Xjitblocking", 13) == 0) {
914 gDvmJit.blockingMode = true;
915 } else if (strncmp(argv[i], "-Xjitthreshold:", 15) == 0) {
916 gDvmJit.threshold = atoi(argv[i] + 15);
917 } else if (strncmp(argv[i], "-Xincludeselectedop", 19) == 0) {
918 gDvmJit.includeSelectedOp = true;
919 } else if (strncmp(argv[i], "-Xincludeselectedmethod", 23) == 0) {
920 gDvmJit.includeSelectedMethod = true;
921 } else if (strncmp(argv[i], "-Xjitcheckcg", 12) == 0) {
922 gDvmJit.checkCallGraph = true;
923 /* Need to enable blocking mode due to stack crawling */
924 gDvmJit.blockingMode = true;
925 } else if (strncmp(argv[i], "-Xjitverbose", 12) == 0) {
926 gDvmJit.printMe = true;
927 } else if (strncmp(argv[i], "-Xjitprofile", 12) == 0) {
928 gDvmJit.profile = true;
929 } else if (strncmp(argv[i], "-Xjitdisableopt", 15) == 0) {
930 /* Disable selected optimizations */
931 if (argv[i][15] == ':') {
932 sscanf(argv[i] + 16, "%x", &gDvmJit.disableOpt);
933 /* Disable all optimizations */
935 gDvmJit.disableOpt = -1;
939 } else if (strncmp(argv[i], "-Xdeadlockpredict:", 18) == 0) {
940 #ifdef WITH_DEADLOCK_PREDICTION
941 if (strcmp(argv[i] + 18, "off") == 0)
942 gDvm.deadlockPredictMode = kDPOff;
943 else if (strcmp(argv[i] + 18, "warn") == 0)
944 gDvm.deadlockPredictMode = kDPWarn;
945 else if (strcmp(argv[i] + 18, "err") == 0)
946 gDvm.deadlockPredictMode = kDPErr;
947 else if (strcmp(argv[i] + 18, "abort") == 0)
948 gDvm.deadlockPredictMode = kDPAbort;
950 dvmFprintf(stderr, "Bad value for -Xdeadlockpredict");
953 if (gDvm.deadlockPredictMode != kDPOff)
954 LOGD("Deadlock prediction enabled (%s)\n", argv[i]+18);
957 } else if (strncmp(argv[i], "-Xstacktracefile:", 17) == 0) {
958 gDvm.stackTraceFile = strdup(argv[i]+17);
960 } else if (strcmp(argv[i], "-Xgenregmap") == 0) {
961 gDvm.generateRegisterMaps = true;
962 LOGV("Register maps will be generated during verification\n");
964 } else if (strncmp(argv[i], "-Xgc:", 5) == 0) {
965 if (strcmp(argv[i] + 5, "precise") == 0)
966 gDvm.preciseGc = true;
967 else if (strcmp(argv[i] + 5, "noprecise") == 0)
968 gDvm.preciseGc = false;
969 else if (strcmp(argv[i] + 5, "preverify") == 0)
970 gDvm.preVerify = true;
971 else if (strcmp(argv[i] + 5, "nopreverify") == 0)
972 gDvm.preVerify = false;
973 else if (strcmp(argv[i] + 5, "postverify") == 0)
974 gDvm.postVerify = true;
975 else if (strcmp(argv[i] + 5, "nopostverify") == 0)
976 gDvm.postVerify = false;
977 else if (strcmp(argv[i] + 5, "concurrent") == 0)
978 gDvm.concurrentMarkSweep = true;
979 else if (strcmp(argv[i] + 5, "noconcurrent") == 0)
980 gDvm.concurrentMarkSweep = false;
981 else if (strcmp(argv[i] + 5, "verifycardtable") == 0)
982 gDvm.verifyCardTable = true;
983 else if (strcmp(argv[i] + 5, "noverifycardtable") == 0)
984 gDvm.verifyCardTable = false;
986 dvmFprintf(stderr, "Bad value for -Xgc");
989 LOGV("Precise GC configured %s\n", gDvm.preciseGc ? "ON" : "OFF");
991 } else if (strcmp(argv[i], "-Xcheckdexsum") == 0) {
992 gDvm.verifyDexChecksum = true;
994 } else if (strcmp(argv[i], "-Xprofile:wallclock") == 0) {
995 gDvm.profilerWallClock = true;
998 if (!ignoreUnrecognized) {
999 dvmFprintf(stderr, "Unrecognized option '%s'\n", argv[i]);
1005 if (gDvm.heapSizeStart > gDvm.heapSizeMax) {
1006 dvmFprintf(stderr, "Heap start size must be <= heap max size\n");
1014 * Set defaults for fields altered or modified by arguments.
1016 * Globals are initialized to 0 (a/k/a NULL or false).
1018 static void setCommandLineDefaults()
1022 envStr = getenv("CLASSPATH");
1024 gDvm.classPathStr = strdup(envStr);
1026 gDvm.classPathStr = strdup(".");
1027 envStr = getenv("BOOTCLASSPATH");
1029 gDvm.bootClassPathStr = strdup(envStr);
1031 gDvm.bootClassPathStr = strdup(".");
1033 /* Defaults overridden by -Xms and -Xmx.
1034 * TODO: base these on a system or application-specific default
1036 gDvm.heapSizeStart = 2 * 1024 * 1024; // Spec says 16MB; too big for us.
1037 gDvm.heapSizeMax = 16 * 1024 * 1024; // Spec says 75% physical mem
1038 gDvm.stackSize = kDefaultStackSize;
1040 gDvm.concurrentMarkSweep = true;
1042 /* gDvm.jdwpSuspend = true; */
1044 /* allowed unless zygote config doesn't allow it */
1045 gDvm.jdwpAllowed = true;
1047 /* default verification and optimization modes */
1048 gDvm.classVerifyMode = VERIFY_MODE_ALL;
1049 gDvm.dexOptMode = OPTIMIZE_MODE_VERIFIED;
1052 * Default execution mode.
1054 * This should probably interact with the mterp code somehow, e.g. if
1055 * we know we're using the "desktop" build we should probably be
1056 * using "portable" rather than "fast".
1058 #if defined(WITH_JIT)
1059 gDvm.executionMode = kExecutionModeJit;
1061 gDvm.executionMode = kExecutionModeInterpFast;
1065 * SMP support is a compile-time define, but we may want to have
1066 * dexopt target a differently-configured device.
1068 gDvm.dexOptForSmp = (ANDROID_SMP != 0);
1073 * Handle a SIGBUS, which frequently occurs because somebody replaced an
1074 * optimized DEX file out from under us.
1076 static void busCatcher(int signum, siginfo_t* info, void* context)
1078 void* addr = info->si_addr;
1080 LOGE("Caught a SIGBUS (%d), addr=%p\n", signum, addr);
1083 * If we return at this point the SIGBUS just keeps happening, so we
1084 * remove the signal handler and allow it to kill us. TODO: restore
1085 * the original, which points to a debuggerd stub; if we don't then
1086 * debuggerd won't be notified.
1088 signal(SIGBUS, SIG_DFL);
1092 * Configure signals. We need to block SIGQUIT so that the signal only
1093 * reaches the dump-stack-trace thread.
1095 * This can be disabled with the "-Xrs" flag.
1097 static void blockSignals()
1103 sigaddset(&mask, SIGQUIT);
1104 sigaddset(&mask, SIGUSR1); // used to initiate heap dump
1105 #if defined(WITH_JIT) && defined(WITH_JIT_TUNING)
1106 sigaddset(&mask, SIGUSR2); // used to investigate JIT internals
1108 //sigaddset(&mask, SIGPIPE);
1109 cc = sigprocmask(SIG_BLOCK, &mask, NULL);
1113 /* TODO: save the old sigaction in a global */
1114 struct sigaction sa;
1115 memset(&sa, 0, sizeof(sa));
1116 sa.sa_sigaction = busCatcher;
1117 sa.sa_flags = SA_SIGINFO;
1118 cc = sigaction(SIGBUS, &sa, NULL);
1124 * VM initialization. Pass in any options provided on the command line.
1125 * Do not pass in the class name or the options for the class.
1127 * Returns 0 on success.
1129 int dvmStartup(int argc, const char* const argv[], bool ignoreUnrecognized,
1134 assert(gDvm.initializing);
1136 LOGV("VM init args (%d):\n", argc);
1137 for (i = 0; i < argc; i++)
1138 LOGV(" %d: '%s'\n", i, argv[i]);
1140 setCommandLineDefaults();
1142 /* prep properties storage */
1143 if (!dvmPropertiesStartup(argc))
1147 * Process the option flags (if any).
1149 cc = dvmProcessOptions(argc, argv, ignoreUnrecognized);
1152 dvmFprintf(stderr, "\n");
1153 dvmUsage("dalvikvm");
1158 #if WITH_EXTRA_GC_CHECKS > 1
1159 /* only "portable" interp has the extra goodies */
1160 if (gDvm.executionMode != kExecutionModeInterpPortable) {
1161 LOGI("Switching to 'portable' interpreter for GC checks\n");
1162 gDvm.executionMode = kExecutionModeInterpPortable;
1166 /* Configure group scheduling capabilities */
1167 if (!access("/dev/cpuctl/tasks", F_OK)) {
1168 LOGV("Using kernel group scheduling");
1169 gDvm.kernelGroupScheduling = 1;
1171 LOGV("Using kernel scheduler policies");
1174 /* configure signal handling */
1175 if (!gDvm.reduceSignals)
1178 /* verify system page size */
1179 if (sysconf(_SC_PAGESIZE) != SYSTEM_PAGE_SIZE) {
1180 LOGE("ERROR: expected page size %d, got %d\n",
1181 SYSTEM_PAGE_SIZE, (int) sysconf(_SC_PAGESIZE));
1186 LOGV("Using executionMode %d\n", gDvm.executionMode);
1187 dvmCheckAsmConstants();
1190 * Initialize components.
1192 if (!dvmAllocTrackerStartup())
1194 if (!dvmGcStartup())
1196 if (!dvmThreadStartup())
1198 if (!dvmInlineNativeStartup())
1200 if (!dvmVerificationStartup())
1202 if (!dvmRegisterMapStartup())
1204 if (!dvmInstanceofStartup())
1206 if (!dvmClassStartup())
1208 if (!dvmThreadObjStartup())
1210 if (!dvmExceptionStartup())
1212 if (!dvmStringInternStartup())
1214 if (!dvmNativeStartup())
1216 if (!dvmInternalNativeStartup())
1218 if (!dvmJniStartup())
1220 if (!dvmReflectStartup())
1222 if (!dvmProfilingStartup())
1225 /* make sure we got these [can this go away?] */
1226 assert(gDvm.classJavaLangClass != NULL);
1227 assert(gDvm.classJavaLangObject != NULL);
1228 //assert(gDvm.classJavaLangString != NULL);
1229 assert(gDvm.classJavaLangThread != NULL);
1230 assert(gDvm.classJavaLangVMThread != NULL);
1231 assert(gDvm.classJavaLangThreadGroup != NULL);
1234 * Make sure these exist. If they don't, we can return a failure out
1235 * of main and nip the whole thing in the bud.
1237 static const char* earlyClasses[] = {
1238 "Ljava/lang/InternalError;",
1239 "Ljava/lang/StackOverflowError;",
1240 "Ljava/lang/UnsatisfiedLinkError;",
1241 "Ljava/lang/NoClassDefFoundError;",
1244 const char** pClassName;
1245 for (pClassName = earlyClasses; *pClassName != NULL; pClassName++) {
1246 if (dvmFindSystemClassNoInit(*pClassName) == NULL)
1251 * Miscellaneous class library validation.
1253 if (!dvmValidateBoxClasses())
1257 * Do the last bits of Thread struct initialization we need to allow
1258 * JNI calls to work.
1260 if (!dvmPrepMainForJni(pEnv))
1264 * Register the system native methods, which are registered through JNI.
1266 if (!registerSystemNatives(pEnv))
1270 * Do some "late" initialization for the memory allocator. This may
1271 * allocate storage and initialize classes.
1273 if (!dvmCreateStockExceptions())
1277 * At this point, the VM is in a pretty good state. Finish prep on
1278 * the main thread (specifically, create a java.lang.Thread object to go
1279 * along with our Thread struct). Note we will probably be executing
1280 * some interpreted class initializer code in here.
1282 if (!dvmPrepMainThread())
1286 * Make sure we haven't accumulated any tracked references. The main
1287 * thread should be starting with a clean slate.
1289 if (dvmReferenceTableEntries(&dvmThreadSelf()->internalLocalRefTable) != 0)
1291 LOGW("Warning: tracked references remain post-initialization\n");
1292 dvmDumpReferenceTable(&dvmThreadSelf()->internalLocalRefTable, "MAIN");
1295 /* general debugging setup */
1296 if (!dvmDebuggerStartup())
1300 * Init for either zygote mode or non-zygote mode. The key difference
1301 * is that we don't start any additional threads in Zygote mode.
1304 if (!dvmInitZygote())
1307 if (!dvmInitAfterZygote())
1314 LOGE("dmvTestHash FAILED\n");
1315 if (false /*noisy!*/ && !dvmTestIndirectRefTable())
1316 LOGE("dvmTestIndirectRefTable FAILED\n");
1319 assert(!dvmCheckException(dvmThreadSelf()));
1320 gDvm.initExceptionCount = 0;
1330 * Register java.* natives from our class libraries. We need to do
1331 * this after we're ready for JNI registration calls, but before we
1332 * do any class initialization.
1334 * If we get this wrong, we will blow up in the ThreadGroup class init if
1335 * interpreted code makes any reference to System. It will likely do this
1336 * since it wants to do some java.io.File setup (e.g. for static in/out/err).
1338 * We need to have gDvm.initializing raised here so that JNI FindClass
1339 * won't try to use the system/application class loader.
1341 static bool registerSystemNatives(JNIEnv* pEnv)
1345 /* main thread is always first in list */
1346 self = gDvm.threadList;
1348 /* must set this before allowing JNI-based method registration */
1349 self->status = THREAD_NATIVE;
1351 if (jniRegisterSystemMethods(pEnv) < 0) {
1352 LOGW("jniRegisterSystemMethods failed\n");
1356 /* back to run mode */
1357 self->status = THREAD_RUNNING;
1364 * Do zygote-mode-only initialization.
1366 static bool dvmInitZygote(void)
1368 /* zygote goes into its own process group */
1375 * Do non-zygote-mode initialization. This is done during VM init for
1376 * standard startup, or after a "zygote fork" when creating a new process.
1378 bool dvmInitAfterZygote(void)
1380 u8 startHeap, startQuit, startJdwp;
1381 u8 endHeap, endQuit, endJdwp;
1383 startHeap = dvmGetRelativeTimeUsec();
1386 * Post-zygote heap initialization, including starting
1387 * the HeapWorker thread.
1389 if (!dvmGcStartupAfterZygote())
1392 endHeap = dvmGetRelativeTimeUsec();
1393 startQuit = dvmGetRelativeTimeUsec();
1395 /* start signal catcher thread that dumps stacks on SIGQUIT */
1396 if (!gDvm.reduceSignals && !gDvm.noQuitHandler) {
1397 if (!dvmSignalCatcherStartup())
1401 /* start stdout/stderr copier, if requested */
1402 if (gDvm.logStdio) {
1403 if (!dvmStdioConverterStartup())
1407 endQuit = dvmGetRelativeTimeUsec();
1408 startJdwp = dvmGetRelativeTimeUsec();
1411 * Start JDWP thread. If the command-line debugger flags specified
1412 * "suspend=y", this will pause the VM. We probably want this to
1415 if (!dvmInitJDWP()) {
1416 LOGD("JDWP init failed; continuing anyway\n");
1419 endJdwp = dvmGetRelativeTimeUsec();
1421 LOGV("thread-start heap=%d quit=%d jdwp=%d total=%d usec\n",
1422 (int)(endHeap-startHeap), (int)(endQuit-startQuit),
1423 (int)(endJdwp-startJdwp), (int)(endJdwp-startHeap));
1426 if (gDvm.executionMode == kExecutionModeJit) {
1427 if (!dvmCompilerStartup())
1436 * Prepare for a connection to a JDWP-compliant debugger.
1438 * Note this needs to happen fairly late in the startup process, because
1439 * we need to have all of the java.* native methods registered (which in
1440 * turn requires JNI to be fully prepped).
1442 * There are several ways to initialize:
1444 * We immediately try to connect to host:port. Bail on failure. On
1445 * success, send VM_START (suspending the VM if "suspend=y").
1446 * server=y suspend=n
1447 * Passively listen for a debugger to connect. Return immediately.
1448 * server=y suspend=y
1449 * Wait until debugger connects. Send VM_START ASAP, suspending the
1450 * VM after the message is sent.
1452 * This gets more complicated with a nonzero value for "timeout".
1454 static bool dvmInitJDWP(void)
1456 assert(!gDvm.zygote);
1459 * Init JDWP if the debugger is enabled. This may connect out to a
1460 * debugger, passively listen for a debugger, or block waiting for a
1463 if (gDvm.jdwpAllowed && gDvm.jdwpConfigured) {
1464 JdwpStartupParams params;
1466 if (gDvm.jdwpHost != NULL) {
1467 if (strlen(gDvm.jdwpHost) >= sizeof(params.host)-1) {
1468 LOGE("ERROR: hostname too long: '%s'\n", gDvm.jdwpHost);
1471 strcpy(params.host, gDvm.jdwpHost);
1473 params.host[0] = '\0';
1475 params.transport = gDvm.jdwpTransport;
1476 params.server = gDvm.jdwpServer;
1477 params.suspend = gDvm.jdwpSuspend;
1478 params.port = gDvm.jdwpPort;
1480 gDvm.jdwpState = dvmJdwpStartup(¶ms);
1481 if (gDvm.jdwpState == NULL) {
1482 LOGW("WARNING: debugger thread failed to initialize\n");
1483 /* TODO: ignore? fail? need to mimic "expected" behavior */
1488 * If a debugger has already attached, send the "welcome" message. This
1489 * may cause us to suspend all threads.
1491 if (dvmJdwpIsActive(gDvm.jdwpState)) {
1492 //dvmChangeStatus(NULL, THREAD_RUNNING);
1493 if (!dvmJdwpPostVMStart(gDvm.jdwpState, gDvm.jdwpSuspend)) {
1494 LOGW("WARNING: failed to post 'start' message to debugger\n");
1497 //dvmChangeStatus(NULL, THREAD_NATIVE);
1504 * An alternative to JNI_CreateJavaVM/dvmStartup that does the first bit
1505 * of initialization and then returns with "initializing" still set. (Used
1506 * by DexOpt command-line utility.)
1508 * Attempting to use JNI or internal natives will fail. It's best if
1509 * no bytecode gets executed, which means no <clinit>, which means no
1510 * exception-throwing. We check the "initializing" flag anyway when
1511 * throwing an exception, so we can insert some code that avoids chucking
1512 * an exception when we're optimizing stuff.
1514 * Returns 0 on success.
1516 int dvmPrepForDexOpt(const char* bootClassPath, DexOptimizerMode dexOptMode,
1517 DexClassVerifyMode verifyMode, int dexoptFlags)
1519 gDvm.initializing = true;
1520 gDvm.optimizing = true;
1522 /* configure signal handling */
1525 /* set some defaults */
1526 setCommandLineDefaults();
1527 free(gDvm.bootClassPathStr);
1528 gDvm.bootClassPathStr = strdup(bootClassPath);
1530 /* set opt/verify modes */
1531 gDvm.dexOptMode = dexOptMode;
1532 gDvm.classVerifyMode = verifyMode;
1533 gDvm.generateRegisterMaps = (dexoptFlags & DEXOPT_GEN_REGISTER_MAPS) != 0;
1536 * Initialize the heap, some basic thread control mutexes, and
1537 * get the bootclasspath prepped.
1539 * We can't load any classes yet because we may not yet have a source
1540 * for things like java.lang.Object and java.lang.Class.
1542 if (!dvmGcStartup())
1544 if (!dvmThreadStartup())
1546 if (!dvmInlineNativeStartup())
1548 if (!dvmVerificationStartup())
1550 if (!dvmRegisterMapStartup())
1552 if (!dvmInstanceofStartup())
1554 if (!dvmClassStartup())
1558 * We leave gDvm.initializing set to "true" so that, if we're not
1559 * able to process the "core" classes, we don't go into a death-spin
1560 * trying to throw a "class not found" exception.
1572 * All threads have stopped. Finish the shutdown procedure.
1574 * We can also be called if startup fails partway through, so be prepared
1575 * to deal with partially initialized data.
1577 * Free any storage allocated in gGlobals.
1579 * We can't dlclose() shared libs we've loaded, because it's possible a
1580 * thread not associated with the VM is running code in one.
1582 * This is called from the JNI DestroyJavaVM function, which can be
1583 * called from any thread. (In practice, this will usually run in the
1584 * same thread that started the VM, a/k/a the main thread, but we don't
1585 * want to assume that.)
1587 void dvmShutdown(void)
1589 LOGV("VM shutting down\n");
1591 if (CALC_CACHE_STATS)
1592 dvmDumpAtomicCacheStats(gDvm.instanceofCache);
1595 * Stop our internal threads.
1597 dvmGcThreadShutdown();
1599 if (gDvm.jdwpState != NULL)
1600 dvmJdwpShutdown(gDvm.jdwpState);
1601 free(gDvm.jdwpHost);
1602 gDvm.jdwpHost = NULL;
1603 free(gDvm.jniTrace);
1604 gDvm.jniTrace = NULL;
1605 free(gDvm.stackTraceFile);
1606 gDvm.stackTraceFile = NULL;
1608 /* tell signal catcher to shut down if it was started */
1609 dvmSignalCatcherShutdown();
1611 /* shut down stdout/stderr conversion */
1612 dvmStdioConverterShutdown();
1615 if (gDvm.executionMode == kExecutionModeJit) {
1616 /* shut down the compiler thread */
1617 dvmCompilerShutdown();
1622 * Kill any daemon threads that still exist. Actively-running threads
1623 * are likely to crash the process if they continue to execute while
1624 * the VM shuts down.
1628 if (gDvm.verboseShutdown)
1629 LOGD("VM cleaning up\n");
1631 dvmDebuggerShutdown();
1632 dvmReflectShutdown();
1633 dvmProfilingShutdown();
1635 dvmStringInternShutdown();
1636 dvmExceptionShutdown();
1637 dvmThreadShutdown();
1639 dvmVerificationShutdown();
1640 dvmRegisterMapShutdown();
1641 dvmInstanceofShutdown();
1642 dvmInlineNativeShutdown();
1644 dvmAllocTrackerShutdown();
1645 dvmPropertiesShutdown();
1647 /* these must happen AFTER dvmClassShutdown has walked through class data */
1648 dvmNativeShutdown();
1649 dvmInternalNativeShutdown();
1651 free(gDvm.bootClassPathStr);
1652 free(gDvm.classPathStr);
1654 freeAssertionCtrl();
1657 * We want valgrind to report anything we forget to free as "definitely
1658 * lost". If there's a pointer in the global chunk, it would be reported
1659 * as "still reachable". Erasing the memory fixes this.
1661 * This must be erased to zero if we want to restart the VM within this
1664 memset(&gDvm, 0xcd, sizeof(gDvm));
1669 * fprintf() wrapper that calls through the JNI-specified vfprintf hook if
1670 * one was specified.
1672 int dvmFprintf(FILE* fp, const char* format, ...)
1677 va_start(args, format);
1678 if (gDvm.vfprintfHook != NULL)
1679 result = (*gDvm.vfprintfHook)(fp, format, args);
1681 result = vfprintf(fp, format, args);
1688 * Abort the VM. We get here on fatal errors. Try very hard not to use
1689 * this; whenever possible, return an error to somebody responsible.
1693 LOGE("VM aborting\n");
1695 fflush(NULL); // flush all open file buffers
1697 /* JNI-supplied abort hook gets right of first refusal */
1698 if (gDvm.abortHook != NULL)
1699 (*gDvm.abortHook)();
1702 * If we call abort(), all threads in the process receives a SIBABRT.
1703 * debuggerd dumps the stack trace of the main thread, whether or not
1704 * that was the thread that failed.
1706 * By stuffing a value into a bogus address, we cause a segmentation
1707 * fault in the current thread, and get a useful log from debuggerd.
1708 * We can also trivially tell the difference between a VM crash and
1709 * a deliberate abort by looking at the fault address.
1711 *((char*)0xdeadd00d) = 38;