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]overwritefree\n");
119 dvmFprintf(stderr, " -Xgc:[no]preverify\n");
120 dvmFprintf(stderr, " -Xgc:[no]postverify\n");
121 dvmFprintf(stderr, " -Xgc:[no]concurrent\n");
122 dvmFprintf(stderr, " -Xgc:[no]verifycardtable\n");
123 dvmFprintf(stderr, " -Xgenregmap\n");
124 dvmFprintf(stderr, " -Xcheckdexsum\n");
125 #if defined(WITH_JIT)
126 dvmFprintf(stderr, " -Xincludeselectedop\n");
127 dvmFprintf(stderr, " -Xjitop:hexopvalue[-endvalue]"
128 "[,hexopvalue[-endvalue]]*\n");
129 dvmFprintf(stderr, " -Xincludeselectedmethod\n");
130 dvmFprintf(stderr, " -Xjitthreshold:decimalvalue\n");
131 dvmFprintf(stderr, " -Xjitblocking\n");
132 dvmFprintf(stderr, " -Xjitmethod:signature[,signature]* "
133 "(eg Ljava/lang/String\\;replace)\n");
134 dvmFprintf(stderr, " -Xjitcheckcg\n");
135 dvmFprintf(stderr, " -Xjitverbose\n");
136 dvmFprintf(stderr, " -Xjitprofile\n");
137 dvmFprintf(stderr, " -Xjitdisableopt\n");
139 dvmFprintf(stderr, "\n");
140 dvmFprintf(stderr, "Configured with:"
147 #ifdef WITH_MONITOR_TRACKING
150 #ifdef WITH_DEADLOCK_PREDICTION
151 " deadlock_prediction"
156 #ifdef WITH_HPROF_STACK
159 #ifdef WITH_ALLOC_LIMITS
162 #ifdef WITH_TRACKREF_CHECKS
165 #ifdef WITH_INSTR_CHECKS
168 #ifdef WITH_EXTRA_OBJECT_VALIDATION
169 " extra_object_validation"
171 #ifdef WITH_EXTRA_GC_CHECKS
174 #ifdef WITH_DALVIK_ASSERT
177 #ifdef WITH_JNI_STACK_CHECK
186 #ifdef PROFILE_FIELD_ACCESS
187 " profile_field_access"
189 #if DVM_RESOLVER_CACHE == DVM_RC_REDUCING
190 " resolver_cache_reducing"
191 #elif DVM_RESOLVER_CACHE == DVM_RC_EXPANDING
192 " resolver_cache_expanding"
193 #elif DVM_RESOLVER_CACHE == DVM_RC_NO_CACHE
194 " resolver_cache_disabled"
196 #if defined(WITH_JIT)
199 #if defined(WITH_SELF_VERIFICATION)
206 #ifdef DVM_SHOW_EXCEPTION
207 dvmFprintf(stderr, " show_exception=%d", DVM_SHOW_EXCEPTION);
209 dvmFprintf(stderr, "\n\n");
213 * Show helpful information on JDWP options.
215 static void showJdwpHelp(void)
218 "Example: -Xrunjdwp:transport=dt_socket,address=8000,server=y\n");
220 "Example: -Xrunjdwp:transport=dt_socket,address=localhost:6500,server=n\n");
224 * Show version and copyright info.
226 static void showVersion(void)
228 dvmFprintf(stdout, "DalvikVM version %d.%d.%d\n",
229 DALVIK_MAJOR_VERSION, DALVIK_MINOR_VERSION, DALVIK_BUG_VERSION);
231 "Copyright (C) 2007 The Android Open Source Project\n\n"
232 "This software is built from source code licensed under the "
234 "Version 2.0 (the \"License\"). You may obtain a copy of the "
236 " http://www.apache.org/licenses/LICENSE-2.0\n\n"
237 "See the associated NOTICE file for this software for further "
242 * Parse a string of the form /[0-9]+[kKmMgG]?/, which is used to specify
243 * memory sizes. [kK] indicates kilobytes, [mM] megabytes, and
246 * "s" should point just past the "-Xm?" part of the string.
247 * "min" specifies the lowest acceptable value described by "s".
248 * "div" specifies a divisor, e.g. 1024 if the value must be a multiple
251 * The spec says the -Xmx and -Xms options must be multiples of 1024. It
252 * doesn't say anything about -Xss.
254 * Returns 0 (a useless size) if "s" is malformed or specifies a low or
255 * non-evenly-divisible value.
257 static unsigned int dvmParseMemOption(const char *s, unsigned int div)
259 /* strtoul accepts a leading [+-], which we don't want,
260 * so make sure our string starts with a decimal digit.
266 val = (unsigned int)strtoul(s, (char **)&s2, 10);
268 /* s2 should be pointing just after the number.
269 * If this is the end of the string, the user
270 * has specified a number of bytes. Otherwise,
271 * there should be exactly one more character
272 * that specifies a multiplier.
277 /* The remainder of the string is either a single multiplier
278 * character, or nothing to indicate that the value is in
287 } else if (c == 'k' || c == 'K') {
289 } else if (c == 'm' || c == 'M') {
291 } else if (c == 'g' || c == 'G') {
292 mul = 1024 * 1024 * 1024;
294 /* Unknown multiplier character.
299 if (val <= UINT_MAX / mul) {
302 /* Clamp to a multiple of 1024.
304 val = UINT_MAX & ~(1024-1);
307 /* There's more than one character after the
314 /* The man page says that a -Xm value must be
315 * a multiple of 1024.
317 if (val % div == 0) {
327 * Handle one of the JDWP name/value pairs.
330 * help: if specified, show help message and bail
331 * transport: may be dt_socket or dt_shmem
332 * address: for dt_socket, "host:port", or just "port" when listening
333 * server: if "y", wait for debugger to attach; if "n", attach to debugger
334 * timeout: how long to wait for debugger to connect / listen
336 * Useful with server=n (these aren't supported yet):
337 * onthrow=<exception-name>: connect to debugger when exception thrown
338 * onuncaught=y|n: connect to debugger when uncaught exception thrown
339 * launch=<command-line>: launch the debugger itself
341 * The "transport" option is required, as is "address" if server=n.
343 static bool handleJdwpOption(const char* name, const char* value)
345 if (strcmp(name, "transport") == 0) {
346 if (strcmp(value, "dt_socket") == 0) {
347 gDvm.jdwpTransport = kJdwpTransportSocket;
348 } else if (strcmp(value, "dt_android_adb") == 0) {
349 gDvm.jdwpTransport = kJdwpTransportAndroidAdb;
351 LOGE("JDWP transport '%s' not supported\n", value);
354 } else if (strcmp(name, "server") == 0) {
356 gDvm.jdwpServer = false;
357 else if (*value == 'y')
358 gDvm.jdwpServer = true;
360 LOGE("JDWP option 'server' must be 'y' or 'n'\n");
363 } else if (strcmp(name, "suspend") == 0) {
365 gDvm.jdwpSuspend = false;
366 else if (*value == 'y')
367 gDvm.jdwpSuspend = true;
369 LOGE("JDWP option 'suspend' must be 'y' or 'n'\n");
372 } else if (strcmp(name, "address") == 0) {
373 /* this is either <port> or <host>:<port> */
374 const char* colon = strchr(value, ':');
380 gDvm.jdwpHost = (char*) malloc(colon - value +1);
381 strncpy(gDvm.jdwpHost, value, colon - value +1);
382 gDvm.jdwpHost[colon-value] = '\0';
385 if (*value == '\0') {
386 LOGE("JDWP address missing port\n");
389 port = strtol(value, &end, 10);
391 LOGE("JDWP address has junk in port field '%s'\n", value);
394 gDvm.jdwpPort = port;
395 } else if (strcmp(name, "launch") == 0 ||
396 strcmp(name, "onthrow") == 0 ||
397 strcmp(name, "oncaught") == 0 ||
398 strcmp(name, "timeout") == 0)
400 /* valid but unsupported */
401 LOGI("Ignoring JDWP option '%s'='%s'\n", name, value);
403 LOGI("Ignoring unrecognized JDWP option '%s'='%s'\n", name, value);
410 * Parse the latter half of a -Xrunjdwp/-agentlib:jdwp= string, e.g.:
411 * "transport=dt_socket,address=8000,server=y,suspend=n"
413 static bool parseJdwpOptions(const char* str)
415 char* mangle = strdup(str);
420 * Process all of the name=value pairs.
426 value = strchr(name, '=');
428 LOGE("JDWP opts: garbage at '%s'\n", name);
432 comma = strchr(name, ','); // use name, not value, for safety
435 LOGE("JDWP opts: found comma before '=' in '%s'\n", mangle);
441 *value++ = '\0'; // stomp the '='
443 if (!handleJdwpOption(name, value))
454 * Make sure the combination of arguments makes sense.
456 if (gDvm.jdwpTransport == kJdwpTransportUnknown) {
457 LOGE("JDWP opts: must specify transport\n");
460 if (!gDvm.jdwpServer && (gDvm.jdwpHost == NULL || gDvm.jdwpPort == 0)) {
461 LOGE("JDWP opts: when server=n, must specify host and port\n");
464 // transport mandatory
465 // outbound server address
467 gDvm.jdwpConfigured = true;
476 * Handle one of the four kinds of assertion arguments.
478 * "pkgOrClass" is the last part of an enable/disable line. For a package
479 * the arg looks like "-ea:com.google.fubar...", for a class it looks
480 * like "-ea:com.google.fubar.Wahoo". The string we get starts at the ':'.
482 * For system assertions (-esa/-dsa), "pkgOrClass" is NULL.
484 * Multiple instances of these arguments can be specified, e.g. you can
485 * enable assertions for a package and then disable them for one class in
488 static bool enableAssertions(const char* pkgOrClass, bool enable)
490 AssertionControl* pCtrl = &gDvm.assertionCtrl[gDvm.assertionCtrlCount++];
491 pCtrl->enable = enable;
493 if (pkgOrClass == NULL) {
494 /* enable or disable for all system classes */
495 pCtrl->isPackage = false;
496 pCtrl->pkgOrClass = NULL;
497 pCtrl->pkgOrClassLen = 0;
499 if (*pkgOrClass == '\0') {
500 /* global enable/disable for all but system */
501 pCtrl->isPackage = false;
502 pCtrl->pkgOrClass = strdup("");
503 pCtrl->pkgOrClassLen = 0;
505 pCtrl->pkgOrClass = dvmDotToSlash(pkgOrClass+1); // skip ':'
506 if (pCtrl->pkgOrClass == NULL) {
507 /* can happen if class name includes an illegal '/' */
508 LOGW("Unable to process assertion arg '%s'\n", pkgOrClass);
512 int len = strlen(pCtrl->pkgOrClass);
513 if (len >= 3 && strcmp(pCtrl->pkgOrClass + len-3, "///") == 0) {
514 /* mark as package, truncate two of the three slashes */
515 pCtrl->isPackage = true;
516 *(pCtrl->pkgOrClass + len-2) = '\0';
517 pCtrl->pkgOrClassLen = len - 2;
520 pCtrl->isPackage = false;
521 pCtrl->pkgOrClassLen = len;
530 * Turn assertions on when requested to do so by the Zygote.
532 * This is a bit sketchy. We can't (easily) go back and fiddle with all
533 * of the classes that have already been initialized, so this only
534 * affects classes that have yet to be loaded. If some or all assertions
535 * have been enabled through some other means, we don't want to mess with
536 * it here, so we do nothing. Finally, we assume that there's room in
537 * "assertionCtrl" to hold at least one entry; this is guaranteed by the
540 * This must only be called from the main thread during zygote init.
542 void dvmLateEnableAssertions(void)
544 if (gDvm.assertionCtrl == NULL) {
545 LOGD("Not late-enabling assertions: no assertionCtrl array\n");
547 } else if (gDvm.assertionCtrlCount != 0) {
548 LOGD("Not late-enabling assertions: some asserts already configured\n");
551 LOGD("Late-enabling assertions\n");
553 /* global enable for all but system */
554 AssertionControl* pCtrl = gDvm.assertionCtrl;
555 pCtrl->pkgOrClass = strdup("");
556 pCtrl->pkgOrClassLen = 0;
557 pCtrl->isPackage = false;
558 pCtrl->enable = true;
559 gDvm.assertionCtrlCount = 1;
564 * Release memory associated with the AssertionCtrl array.
566 static void freeAssertionCtrl(void)
570 for (i = 0; i < gDvm.assertionCtrlCount; i++)
571 free(gDvm.assertionCtrl[i].pkgOrClass);
572 free(gDvm.assertionCtrl);
575 #if defined(WITH_JIT)
576 /* Parse -Xjitop to selectively turn on/off certain opcodes for JIT */
577 static void processXjitop(const char *opt)
580 const char *startPtr = &opt[8];
584 long startValue, endValue;
586 startValue = strtol(startPtr, &endPtr, 16);
587 if (startPtr != endPtr) {
588 /* Just in case value is out of range */
591 if (*endPtr == '-') {
592 endValue = strtol(endPtr+1, &endPtr, 16);
595 endValue = startValue;
598 for (; startValue <= endValue; startValue++) {
599 LOGW("Dalvik opcode %x is selected for debugging",
600 (unsigned int) startValue);
601 /* Mark the corresponding bit to 1 */
602 gDvmJit.opList[startValue >> 3] |=
603 1 << (startValue & 0x7);
610 startPtr = endPtr + 1;
616 "Warning: Unrecognized opcode value substring "
624 for (i = 0; i < 32; i++) {
625 gDvmJit.opList[i] = 0xff;
627 dvmFprintf(stderr, "Warning: select all opcodes\n");
631 /* Parse -Xjitmethod to selectively turn on/off certain methods for JIT */
632 static void processXjitmethod(const char *opt)
634 char *buf = strdup(&opt[12]);
637 gDvmJit.methodTable = dvmHashTableCreate(8, NULL);
641 * Break comma-separated method signatures and enter them into the hash
642 * table individually.
647 end = strchr(start, ',');
652 hashValue = dvmComputeUtf8Hash(start);
654 dvmHashTableLookup(gDvmJit.methodTable, hashValue,
656 (HashCompareFunc) strcmp, true);
668 * Process an argument vector full of options. Unlike standard C programs,
669 * argv[0] does not contain the name of the program.
671 * If "ignoreUnrecognized" is set, we ignore options starting with "-X" or "_"
672 * that we don't recognize. Otherwise, we return with an error as soon as
673 * we see anything we can't identify.
675 * Returns 0 on success, -1 on failure, and 1 for the special case of
676 * "-version" where we want to stop without showing an error message.
678 static int dvmProcessOptions(int argc, const char* const argv[],
679 bool ignoreUnrecognized)
683 LOGV("VM options (%d):\n", argc);
684 for (i = 0; i < argc; i++)
685 LOGV(" %d: '%s'\n", i, argv[i]);
688 * Over-allocate AssertionControl array for convenience. If allocated,
689 * the array must be able to hold at least one entry, so that the
690 * zygote-time activation can do its business.
692 assert(gDvm.assertionCtrl == NULL);
695 (AssertionControl*) malloc(sizeof(AssertionControl) * argc);
696 if (gDvm.assertionCtrl == NULL)
698 assert(gDvm.assertionCtrlCount == 0);
701 for (i = 0; i < argc; i++) {
702 if (strcmp(argv[i], "-help") == 0) {
703 /* show usage and stop */
706 } else if (strcmp(argv[i], "-version") == 0) {
707 /* show version and stop */
710 } else if (strcmp(argv[i], "-showversion") == 0) {
711 /* show version and continue */
714 } else if (strcmp(argv[i], "-classpath") == 0 ||
715 strcmp(argv[i], "-cp") == 0)
719 dvmFprintf(stderr, "Missing classpath path list\n");
722 free(gDvm.classPathStr); /* in case we have compiled-in default */
723 gDvm.classPathStr = strdup(argv[++i]);
725 } else if (strncmp(argv[i], "-Xbootclasspath:",
726 sizeof("-Xbootclasspath:")-1) == 0)
728 /* set bootclasspath */
729 const char* path = argv[i] + sizeof("-Xbootclasspath:")-1;
732 dvmFprintf(stderr, "Missing bootclasspath path list\n");
735 free(gDvm.bootClassPathStr);
736 gDvm.bootClassPathStr = strdup(path);
739 * TODO: support -Xbootclasspath/a and /p, which append or
740 * prepend to the default bootclasspath. We set the default
744 } else if (strncmp(argv[i], "-D", 2) == 0) {
746 dvmAddCommandLineProperty(argv[i] + 2);
748 } else if (strcmp(argv[i], "-jar") == 0) {
749 // TODO: handle this; name of jar should be in argv[i+1]
750 dvmFprintf(stderr, "-jar not yet handled\n");
753 } else if (strncmp(argv[i], "-Xms", 4) == 0) {
754 unsigned int val = dvmParseMemOption(argv[i]+4, 1024);
756 if (val >= kMinHeapStartSize && val <= kMaxHeapSize) {
757 gDvm.heapSizeStart = val;
760 "Invalid -Xms '%s', range is %dKB to %dKB\n",
761 argv[i], kMinHeapStartSize/1024, kMaxHeapSize/1024);
765 dvmFprintf(stderr, "Invalid -Xms option '%s'\n", argv[i]);
768 } else if (strncmp(argv[i], "-Xmx", 4) == 0) {
769 unsigned int val = dvmParseMemOption(argv[i]+4, 1024);
771 if (val >= kMinHeapSize && val <= kMaxHeapSize) {
772 gDvm.heapSizeMax = val;
775 "Invalid -Xmx '%s', range is %dKB to %dKB\n",
776 argv[i], kMinHeapSize/1024, kMaxHeapSize/1024);
780 dvmFprintf(stderr, "Invalid -Xmx option '%s'\n", argv[i]);
783 } else if (strncmp(argv[i], "-Xss", 4) == 0) {
784 unsigned int val = dvmParseMemOption(argv[i]+4, 1);
786 if (val >= kMinStackSize && val <= kMaxStackSize) {
787 gDvm.stackSize = val;
789 dvmFprintf(stderr, "Invalid -Xss '%s', range is %d to %d\n",
790 argv[i], kMinStackSize, kMaxStackSize);
794 dvmFprintf(stderr, "Invalid -Xss option '%s'\n", argv[i]);
798 } else if (strcmp(argv[i], "-verbose") == 0 ||
799 strcmp(argv[i], "-verbose:class") == 0)
801 // JNI spec says "-verbose:gc,class" is valid, but cmd line
802 // doesn't work that way; may want to support.
803 gDvm.verboseClass = true;
804 } else if (strcmp(argv[i], "-verbose:jni") == 0) {
805 gDvm.verboseJni = true;
806 } else if (strcmp(argv[i], "-verbose:gc") == 0) {
807 gDvm.verboseGc = true;
808 } else if (strcmp(argv[i], "-verbose:shutdown") == 0) {
809 gDvm.verboseShutdown = true;
811 } else if (strncmp(argv[i], "-enableassertions", 17) == 0) {
812 enableAssertions(argv[i] + 17, true);
813 } else if (strncmp(argv[i], "-ea", 3) == 0) {
814 enableAssertions(argv[i] + 3, true);
815 } else if (strncmp(argv[i], "-disableassertions", 18) == 0) {
816 enableAssertions(argv[i] + 18, false);
817 } else if (strncmp(argv[i], "-da", 3) == 0) {
818 enableAssertions(argv[i] + 3, false);
819 } else if (strcmp(argv[i], "-enablesystemassertions") == 0 ||
820 strcmp(argv[i], "-esa") == 0)
822 enableAssertions(NULL, true);
823 } else if (strcmp(argv[i], "-disablesystemassertions") == 0 ||
824 strcmp(argv[i], "-dsa") == 0)
826 enableAssertions(NULL, false);
828 } else if (strncmp(argv[i], "-Xcheck:jni", 11) == 0) {
829 /* nothing to do now -- was handled during JNI init */
831 } else if (strcmp(argv[i], "-Xdebug") == 0) {
832 /* accept but ignore */
834 } else if (strncmp(argv[i], "-Xrunjdwp:", 10) == 0 ||
835 strncmp(argv[i], "-agentlib:jdwp=", 15) == 0)
839 if (argv[i][1] == 'X')
844 if (strncmp(tail, "help", 4) == 0 || !parseJdwpOptions(tail)) {
848 } else if (strcmp(argv[i], "-Xrs") == 0) {
849 gDvm.reduceSignals = true;
850 } else if (strcmp(argv[i], "-Xnoquithandler") == 0) {
851 /* disables SIGQUIT handler thread while still blocking SIGQUIT */
852 /* (useful if we don't want thread but system still signals us) */
853 gDvm.noQuitHandler = true;
854 } else if (strcmp(argv[i], "-Xzygote") == 0) {
856 #if defined(WITH_JIT)
857 gDvmJit.runningInAndroidFramework = true;
859 } else if (strncmp(argv[i], "-Xdexopt:", 9) == 0) {
860 if (strcmp(argv[i] + 9, "none") == 0)
861 gDvm.dexOptMode = OPTIMIZE_MODE_NONE;
862 else if (strcmp(argv[i] + 9, "verified") == 0)
863 gDvm.dexOptMode = OPTIMIZE_MODE_VERIFIED;
864 else if (strcmp(argv[i] + 9, "all") == 0)
865 gDvm.dexOptMode = OPTIMIZE_MODE_ALL;
867 dvmFprintf(stderr, "Unrecognized dexopt option '%s'\n",argv[i]);
870 } else if (strncmp(argv[i], "-Xverify:", 9) == 0) {
871 if (strcmp(argv[i] + 9, "none") == 0)
872 gDvm.classVerifyMode = VERIFY_MODE_NONE;
873 else if (strcmp(argv[i] + 9, "remote") == 0)
874 gDvm.classVerifyMode = VERIFY_MODE_REMOTE;
875 else if (strcmp(argv[i] + 9, "all") == 0)
876 gDvm.classVerifyMode = VERIFY_MODE_ALL;
878 dvmFprintf(stderr, "Unrecognized verify option '%s'\n",argv[i]);
881 } else if (strncmp(argv[i], "-Xjnigreflimit:", 15) == 0) {
882 int lim = atoi(argv[i] + 15);
883 if (lim < 200 || (lim % 100) != 0) {
884 dvmFprintf(stderr, "Bad value for -Xjnigreflimit: '%s'\n",
888 gDvm.jniGrefLimit = lim;
889 } else if (strncmp(argv[i], "-Xjnitrace:", 11) == 0) {
890 gDvm.jniTrace = strdup(argv[i] + 11);
891 } else if (strcmp(argv[i], "-Xlog-stdio") == 0) {
892 gDvm.logStdio = true;
894 } else if (strncmp(argv[i], "-Xint", 5) == 0) {
895 if (argv[i][5] == ':') {
896 if (strcmp(argv[i] + 6, "portable") == 0)
897 gDvm.executionMode = kExecutionModeInterpPortable;
898 else if (strcmp(argv[i] + 6, "fast") == 0)
899 gDvm.executionMode = kExecutionModeInterpFast;
901 else if (strcmp(argv[i] + 6, "jit") == 0)
902 gDvm.executionMode = kExecutionModeJit;
906 "Warning: Unrecognized interpreter mode %s\n",argv[i]);
910 /* disable JIT if it was enabled by default */
911 gDvm.executionMode = kExecutionModeInterpFast;
914 } else if (strncmp(argv[i], "-Xlockprofthreshold:", 20) == 0) {
915 gDvm.lockProfThreshold = atoi(argv[i] + 20);
918 } else if (strncmp(argv[i], "-Xjitop", 7) == 0) {
919 processXjitop(argv[i]);
920 } else if (strncmp(argv[i], "-Xjitmethod", 11) == 0) {
921 processXjitmethod(argv[i]);
922 } else if (strncmp(argv[i], "-Xjitblocking", 13) == 0) {
923 gDvmJit.blockingMode = true;
924 } else if (strncmp(argv[i], "-Xjitthreshold:", 15) == 0) {
925 gDvmJit.threshold = atoi(argv[i] + 15);
926 } else if (strncmp(argv[i], "-Xincludeselectedop", 19) == 0) {
927 gDvmJit.includeSelectedOp = true;
928 } else if (strncmp(argv[i], "-Xincludeselectedmethod", 23) == 0) {
929 gDvmJit.includeSelectedMethod = true;
930 } else if (strncmp(argv[i], "-Xjitcheckcg", 12) == 0) {
931 gDvmJit.checkCallGraph = true;
932 /* Need to enable blocking mode due to stack crawling */
933 gDvmJit.blockingMode = true;
934 } else if (strncmp(argv[i], "-Xjitverbose", 12) == 0) {
935 gDvmJit.printMe = true;
936 } else if (strncmp(argv[i], "-Xjitprofile", 12) == 0) {
937 gDvmJit.profile = true;
938 } else if (strncmp(argv[i], "-Xjitdisableopt", 15) == 0) {
939 /* Disable selected optimizations */
940 if (argv[i][15] == ':') {
941 sscanf(argv[i] + 16, "%x", &gDvmJit.disableOpt);
942 /* Disable all optimizations */
944 gDvmJit.disableOpt = -1;
948 } else if (strncmp(argv[i], "-Xdeadlockpredict:", 18) == 0) {
949 #ifdef WITH_DEADLOCK_PREDICTION
950 if (strcmp(argv[i] + 18, "off") == 0)
951 gDvm.deadlockPredictMode = kDPOff;
952 else if (strcmp(argv[i] + 18, "warn") == 0)
953 gDvm.deadlockPredictMode = kDPWarn;
954 else if (strcmp(argv[i] + 18, "err") == 0)
955 gDvm.deadlockPredictMode = kDPErr;
956 else if (strcmp(argv[i] + 18, "abort") == 0)
957 gDvm.deadlockPredictMode = kDPAbort;
959 dvmFprintf(stderr, "Bad value for -Xdeadlockpredict");
962 if (gDvm.deadlockPredictMode != kDPOff)
963 LOGD("Deadlock prediction enabled (%s)\n", argv[i]+18);
966 } else if (strncmp(argv[i], "-Xstacktracefile:", 17) == 0) {
967 gDvm.stackTraceFile = strdup(argv[i]+17);
969 } else if (strcmp(argv[i], "-Xgenregmap") == 0) {
970 gDvm.generateRegisterMaps = true;
971 LOGV("Register maps will be generated during verification\n");
973 } else if (strncmp(argv[i], "-Xgc:", 5) == 0) {
974 if (strcmp(argv[i] + 5, "precise") == 0)
975 gDvm.preciseGc = true;
976 else if (strcmp(argv[i] + 5, "noprecise") == 0)
977 gDvm.preciseGc = false;
978 else if (strcmp(argv[i] + 5, "overwritefree") == 0)
979 gDvm.overwriteFree = true;
980 else if (strcmp(argv[i] + 5, "nooverwritefree") == 0)
981 gDvm.overwriteFree = false;
982 else if (strcmp(argv[i] + 5, "preverify") == 0)
983 gDvm.preVerify = true;
984 else if (strcmp(argv[i] + 5, "nopreverify") == 0)
985 gDvm.preVerify = false;
986 else if (strcmp(argv[i] + 5, "postverify") == 0)
987 gDvm.postVerify = true;
988 else if (strcmp(argv[i] + 5, "nopostverify") == 0)
989 gDvm.postVerify = false;
990 else if (strcmp(argv[i] + 5, "concurrent") == 0)
991 gDvm.concurrentMarkSweep = true;
992 else if (strcmp(argv[i] + 5, "noconcurrent") == 0)
993 gDvm.concurrentMarkSweep = false;
994 else if (strcmp(argv[i] + 5, "verifycardtable") == 0)
995 gDvm.verifyCardTable = true;
996 else if (strcmp(argv[i] + 5, "noverifycardtable") == 0)
997 gDvm.verifyCardTable = false;
999 dvmFprintf(stderr, "Bad value for -Xgc");
1002 LOGV("Precise GC configured %s\n", gDvm.preciseGc ? "ON" : "OFF");
1004 } else if (strcmp(argv[i], "-Xcheckdexsum") == 0) {
1005 gDvm.verifyDexChecksum = true;
1008 if (!ignoreUnrecognized) {
1009 dvmFprintf(stderr, "Unrecognized option '%s'\n", argv[i]);
1015 if (gDvm.heapSizeStart > gDvm.heapSizeMax) {
1016 dvmFprintf(stderr, "Heap start size must be <= heap max size\n");
1024 * Set defaults for fields altered or modified by arguments.
1026 * Globals are initialized to 0 (a/k/a NULL or false).
1028 static void setCommandLineDefaults()
1032 envStr = getenv("CLASSPATH");
1034 gDvm.classPathStr = strdup(envStr);
1036 gDvm.classPathStr = strdup(".");
1037 envStr = getenv("BOOTCLASSPATH");
1039 gDvm.bootClassPathStr = strdup(envStr);
1041 gDvm.bootClassPathStr = strdup(".");
1043 /* Defaults overridden by -Xms and -Xmx.
1044 * TODO: base these on a system or application-specific default
1046 gDvm.heapSizeStart = 2 * 1024 * 1024; // Spec says 16MB; too big for us.
1047 gDvm.heapSizeMax = 16 * 1024 * 1024; // Spec says 75% physical mem
1048 gDvm.stackSize = kDefaultStackSize;
1050 gDvm.concurrentMarkSweep = true;
1052 /* gDvm.jdwpSuspend = true; */
1054 /* allowed unless zygote config doesn't allow it */
1055 gDvm.jdwpAllowed = true;
1057 /* default verification and optimization modes */
1058 gDvm.classVerifyMode = VERIFY_MODE_ALL;
1059 gDvm.dexOptMode = OPTIMIZE_MODE_VERIFIED;
1062 * Default execution mode.
1064 * This should probably interact with the mterp code somehow, e.g. if
1065 * we know we're using the "desktop" build we should probably be
1066 * using "portable" rather than "fast".
1068 #if defined(WITH_JIT)
1069 gDvm.executionMode = kExecutionModeJit;
1071 gDvm.executionMode = kExecutionModeInterpFast;
1077 * Handle a SIGBUS, which frequently occurs because somebody replaced an
1078 * optimized DEX file out from under us.
1080 static void busCatcher(int signum, siginfo_t* info, void* context)
1082 void* addr = info->si_addr;
1084 LOGE("Caught a SIGBUS (%d), addr=%p\n", signum, addr);
1087 * If we return at this point the SIGBUS just keeps happening, so we
1088 * remove the signal handler and allow it to kill us. TODO: restore
1089 * the original, which points to a debuggerd stub; if we don't then
1090 * debuggerd won't be notified.
1092 signal(SIGBUS, SIG_DFL);
1096 * Configure signals. We need to block SIGQUIT so that the signal only
1097 * reaches the dump-stack-trace thread.
1099 * This can be disabled with the "-Xrs" flag.
1101 static void blockSignals()
1107 sigaddset(&mask, SIGQUIT);
1108 sigaddset(&mask, SIGUSR1); // used to initiate heap dump
1109 #if defined(WITH_JIT) && defined(WITH_JIT_TUNING)
1110 sigaddset(&mask, SIGUSR2); // used to investigate JIT internals
1112 //sigaddset(&mask, SIGPIPE);
1113 cc = sigprocmask(SIG_BLOCK, &mask, NULL);
1117 /* TODO: save the old sigaction in a global */
1118 struct sigaction sa;
1119 memset(&sa, 0, sizeof(sa));
1120 sa.sa_sigaction = busCatcher;
1121 sa.sa_flags = SA_SIGINFO;
1122 cc = sigaction(SIGBUS, &sa, NULL);
1128 * VM initialization. Pass in any options provided on the command line.
1129 * Do not pass in the class name or the options for the class.
1131 * Returns 0 on success.
1133 int dvmStartup(int argc, const char* const argv[], bool ignoreUnrecognized,
1138 assert(gDvm.initializing);
1140 LOGV("VM init args (%d):\n", argc);
1141 for (i = 0; i < argc; i++)
1142 LOGV(" %d: '%s'\n", i, argv[i]);
1144 setCommandLineDefaults();
1146 /* prep properties storage */
1147 if (!dvmPropertiesStartup(argc))
1151 * Process the option flags (if any).
1153 cc = dvmProcessOptions(argc, argv, ignoreUnrecognized);
1156 dvmFprintf(stderr, "\n");
1157 dvmUsage("dalvikvm");
1162 #if WITH_EXTRA_GC_CHECKS > 1
1163 /* only "portable" interp has the extra goodies */
1164 if (gDvm.executionMode != kExecutionModeInterpPortable) {
1165 LOGI("Switching to 'portable' interpreter for GC checks\n");
1166 gDvm.executionMode = kExecutionModeInterpPortable;
1170 /* Configure group scheduling capabilities */
1171 if (!access("/dev/cpuctl/tasks", F_OK)) {
1172 LOGV("Using kernel group scheduling");
1173 gDvm.kernelGroupScheduling = 1;
1175 LOGV("Using kernel scheduler policies");
1178 /* configure signal handling */
1179 if (!gDvm.reduceSignals)
1182 /* verify system page size */
1183 if (sysconf(_SC_PAGESIZE) != SYSTEM_PAGE_SIZE) {
1184 LOGE("ERROR: expected page size %d, got %d\n",
1185 SYSTEM_PAGE_SIZE, (int) sysconf(_SC_PAGESIZE));
1190 LOGV("Using executionMode %d\n", gDvm.executionMode);
1191 dvmCheckAsmConstants();
1194 * Initialize components.
1196 if (!dvmAllocTrackerStartup())
1198 if (!dvmGcStartup())
1200 if (!dvmThreadStartup())
1202 if (!dvmInlineNativeStartup())
1204 if (!dvmVerificationStartup())
1206 if (!dvmRegisterMapStartup())
1208 if (!dvmInstanceofStartup())
1210 if (!dvmClassStartup())
1212 if (!dvmThreadObjStartup())
1214 if (!dvmExceptionStartup())
1216 if (!dvmStringInternStartup())
1218 if (!dvmNativeStartup())
1220 if (!dvmInternalNativeStartup())
1222 if (!dvmJniStartup())
1224 if (!dvmReflectStartup())
1226 #ifdef WITH_PROFILER
1227 if (!dvmProfilingStartup())
1231 /* make sure we got these [can this go away?] */
1232 assert(gDvm.classJavaLangClass != NULL);
1233 assert(gDvm.classJavaLangObject != NULL);
1234 //assert(gDvm.classJavaLangString != NULL);
1235 assert(gDvm.classJavaLangThread != NULL);
1236 assert(gDvm.classJavaLangVMThread != NULL);
1237 assert(gDvm.classJavaLangThreadGroup != NULL);
1240 * Make sure these exist. If they don't, we can return a failure out
1241 * of main and nip the whole thing in the bud.
1243 static const char* earlyClasses[] = {
1244 "Ljava/lang/InternalError;",
1245 "Ljava/lang/StackOverflowError;",
1246 "Ljava/lang/UnsatisfiedLinkError;",
1247 "Ljava/lang/NoClassDefFoundError;",
1250 const char** pClassName;
1251 for (pClassName = earlyClasses; *pClassName != NULL; pClassName++) {
1252 if (dvmFindSystemClassNoInit(*pClassName) == NULL)
1257 * Miscellaneous class library validation.
1259 if (!dvmValidateBoxClasses())
1263 * Do the last bits of Thread struct initialization we need to allow
1264 * JNI calls to work.
1266 if (!dvmPrepMainForJni(pEnv))
1270 * Register the system native methods, which are registered through JNI.
1272 if (!registerSystemNatives(pEnv))
1276 * Do some "late" initialization for the memory allocator. This may
1277 * allocate storage and initialize classes.
1279 if (!dvmCreateStockExceptions())
1283 * At this point, the VM is in a pretty good state. Finish prep on
1284 * the main thread (specifically, create a java.lang.Thread object to go
1285 * along with our Thread struct). Note we will probably be executing
1286 * some interpreted class initializer code in here.
1288 if (!dvmPrepMainThread())
1292 * Make sure we haven't accumulated any tracked references. The main
1293 * thread should be starting with a clean slate.
1295 if (dvmReferenceTableEntries(&dvmThreadSelf()->internalLocalRefTable) != 0)
1297 LOGW("Warning: tracked references remain post-initialization\n");
1298 dvmDumpReferenceTable(&dvmThreadSelf()->internalLocalRefTable, "MAIN");
1301 /* general debugging setup */
1302 if (!dvmDebuggerStartup())
1306 * Init for either zygote mode or non-zygote mode. The key difference
1307 * is that we don't start any additional threads in Zygote mode.
1310 if (!dvmInitZygote())
1313 if (!dvmInitAfterZygote())
1320 LOGE("dmvTestHash FAILED\n");
1321 if (false /*noisy!*/ && !dvmTestIndirectRefTable())
1322 LOGE("dvmTestIndirectRefTable FAILED\n");
1325 assert(!dvmCheckException(dvmThreadSelf()));
1326 gDvm.initExceptionCount = 0;
1336 * Register java.* natives from our class libraries. We need to do
1337 * this after we're ready for JNI registration calls, but before we
1338 * do any class initialization.
1340 * If we get this wrong, we will blow up in the ThreadGroup class init if
1341 * interpreted code makes any reference to System. It will likely do this
1342 * since it wants to do some java.io.File setup (e.g. for static in/out/err).
1344 * We need to have gDvm.initializing raised here so that JNI FindClass
1345 * won't try to use the system/application class loader.
1347 static bool registerSystemNatives(JNIEnv* pEnv)
1351 /* main thread is always first in list */
1352 self = gDvm.threadList;
1354 /* must set this before allowing JNI-based method registration */
1355 self->status = THREAD_NATIVE;
1357 if (jniRegisterSystemMethods(pEnv) < 0) {
1358 LOGW("jniRegisterSystemMethods failed\n");
1362 /* back to run mode */
1363 self->status = THREAD_RUNNING;
1370 * Do zygote-mode-only initialization.
1372 static bool dvmInitZygote(void)
1374 /* zygote goes into its own process group */
1381 * Do non-zygote-mode initialization. This is done during VM init for
1382 * standard startup, or after a "zygote fork" when creating a new process.
1384 bool dvmInitAfterZygote(void)
1386 u8 startHeap, startQuit, startJdwp;
1387 u8 endHeap, endQuit, endJdwp;
1389 startHeap = dvmGetRelativeTimeUsec();
1392 * Post-zygote heap initialization, including starting
1393 * the HeapWorker thread.
1395 if (!dvmGcStartupAfterZygote())
1398 endHeap = dvmGetRelativeTimeUsec();
1399 startQuit = dvmGetRelativeTimeUsec();
1401 /* start signal catcher thread that dumps stacks on SIGQUIT */
1402 if (!gDvm.reduceSignals && !gDvm.noQuitHandler) {
1403 if (!dvmSignalCatcherStartup())
1407 /* start stdout/stderr copier, if requested */
1408 if (gDvm.logStdio) {
1409 if (!dvmStdioConverterStartup())
1413 endQuit = dvmGetRelativeTimeUsec();
1414 startJdwp = dvmGetRelativeTimeUsec();
1417 * Start JDWP thread. If the command-line debugger flags specified
1418 * "suspend=y", this will pause the VM. We probably want this to
1421 if (!dvmInitJDWP()) {
1422 LOGD("JDWP init failed; continuing anyway\n");
1425 endJdwp = dvmGetRelativeTimeUsec();
1427 LOGV("thread-start heap=%d quit=%d jdwp=%d total=%d usec\n",
1428 (int)(endHeap-startHeap), (int)(endQuit-startQuit),
1429 (int)(endJdwp-startJdwp), (int)(endJdwp-startHeap));
1432 if (gDvm.executionMode == kExecutionModeJit) {
1433 if (!dvmCompilerStartup())
1442 * Prepare for a connection to a JDWP-compliant debugger.
1444 * Note this needs to happen fairly late in the startup process, because
1445 * we need to have all of the java.* native methods registered (which in
1446 * turn requires JNI to be fully prepped).
1448 * There are several ways to initialize:
1450 * We immediately try to connect to host:port. Bail on failure. On
1451 * success, send VM_START (suspending the VM if "suspend=y").
1452 * server=y suspend=n
1453 * Passively listen for a debugger to connect. Return immediately.
1454 * server=y suspend=y
1455 * Wait until debugger connects. Send VM_START ASAP, suspending the
1456 * VM after the message is sent.
1458 * This gets more complicated with a nonzero value for "timeout".
1460 static bool dvmInitJDWP(void)
1462 assert(!gDvm.zygote);
1464 #ifndef WITH_DEBUGGER
1465 LOGI("Debugger support not compiled into VM\n");
1470 * Init JDWP if the debugger is enabled. This may connect out to a
1471 * debugger, passively listen for a debugger, or block waiting for a
1474 if (gDvm.jdwpAllowed && gDvm.jdwpConfigured) {
1475 JdwpStartupParams params;
1477 if (gDvm.jdwpHost != NULL) {
1478 if (strlen(gDvm.jdwpHost) >= sizeof(params.host)-1) {
1479 LOGE("ERROR: hostname too long: '%s'\n", gDvm.jdwpHost);
1482 strcpy(params.host, gDvm.jdwpHost);
1484 params.host[0] = '\0';
1486 params.transport = gDvm.jdwpTransport;
1487 params.server = gDvm.jdwpServer;
1488 params.suspend = gDvm.jdwpSuspend;
1489 params.port = gDvm.jdwpPort;
1491 gDvm.jdwpState = dvmJdwpStartup(¶ms);
1492 if (gDvm.jdwpState == NULL) {
1493 LOGW("WARNING: debugger thread failed to initialize\n");
1494 /* TODO: ignore? fail? need to mimic "expected" behavior */
1499 * If a debugger has already attached, send the "welcome" message. This
1500 * may cause us to suspend all threads.
1502 if (dvmJdwpIsActive(gDvm.jdwpState)) {
1503 //dvmChangeStatus(NULL, THREAD_RUNNING);
1504 if (!dvmJdwpPostVMStart(gDvm.jdwpState, gDvm.jdwpSuspend)) {
1505 LOGW("WARNING: failed to post 'start' message to debugger\n");
1508 //dvmChangeStatus(NULL, THREAD_NATIVE);
1515 * An alternative to JNI_CreateJavaVM/dvmStartup that does the first bit
1516 * of initialization and then returns with "initializing" still set. (Used
1517 * by DexOpt command-line utility.)
1519 * Attempting to use JNI or internal natives will fail. It's best if
1520 * no bytecode gets executed, which means no <clinit>, which means no
1521 * exception-throwing. We check the "initializing" flag anyway when
1522 * throwing an exception, so we can insert some code that avoids chucking
1523 * an exception when we're optimizing stuff.
1525 * Returns 0 on success.
1527 int dvmPrepForDexOpt(const char* bootClassPath, DexOptimizerMode dexOptMode,
1528 DexClassVerifyMode verifyMode, int dexoptFlags)
1530 gDvm.initializing = true;
1531 gDvm.optimizing = true;
1533 /* configure signal handling */
1536 /* set some defaults */
1537 setCommandLineDefaults();
1538 free(gDvm.bootClassPathStr);
1539 gDvm.bootClassPathStr = strdup(bootClassPath);
1541 /* set opt/verify modes */
1542 gDvm.dexOptMode = dexOptMode;
1543 gDvm.classVerifyMode = verifyMode;
1544 gDvm.generateRegisterMaps = (dexoptFlags & DEXOPT_GEN_REGISTER_MAPS) != 0;
1547 * Initialize the heap, some basic thread control mutexes, and
1548 * get the bootclasspath prepped.
1550 * We can't load any classes yet because we may not yet have a source
1551 * for things like java.lang.Object and java.lang.Class.
1553 if (!dvmGcStartup())
1555 if (!dvmThreadStartup())
1557 if (!dvmInlineNativeStartup())
1559 if (!dvmVerificationStartup())
1561 if (!dvmRegisterMapStartup())
1563 if (!dvmInstanceofStartup())
1565 if (!dvmClassStartup())
1569 * We leave gDvm.initializing set to "true" so that, if we're not
1570 * able to process the "core" classes, we don't go into a death-spin
1571 * trying to throw a "class not found" exception.
1583 * All threads have stopped. Finish the shutdown procedure.
1585 * We can also be called if startup fails partway through, so be prepared
1586 * to deal with partially initialized data.
1588 * Free any storage allocated in gGlobals.
1590 * We can't dlclose() shared libs we've loaded, because it's possible a
1591 * thread not associated with the VM is running code in one.
1593 * This is called from the JNI DestroyJavaVM function, which can be
1594 * called from any thread. (In practice, this will usually run in the
1595 * same thread that started the VM, a/k/a the main thread, but we don't
1596 * want to assume that.)
1598 void dvmShutdown(void)
1600 LOGV("VM shutting down\n");
1602 if (CALC_CACHE_STATS)
1603 dvmDumpAtomicCacheStats(gDvm.instanceofCache);
1606 * Stop our internal threads.
1608 dvmGcThreadShutdown();
1610 if (gDvm.jdwpState != NULL)
1611 dvmJdwpShutdown(gDvm.jdwpState);
1612 free(gDvm.jdwpHost);
1613 gDvm.jdwpHost = NULL;
1614 free(gDvm.jniTrace);
1615 gDvm.jniTrace = NULL;
1616 free(gDvm.stackTraceFile);
1617 gDvm.stackTraceFile = NULL;
1619 /* tell signal catcher to shut down if it was started */
1620 dvmSignalCatcherShutdown();
1622 /* shut down stdout/stderr conversion */
1623 dvmStdioConverterShutdown();
1626 if (gDvm.executionMode == kExecutionModeJit) {
1627 /* shut down the compiler thread */
1628 dvmCompilerShutdown();
1633 * Kill any daemon threads that still exist. Actively-running threads
1634 * are likely to crash the process if they continue to execute while
1635 * the VM shuts down.
1639 if (gDvm.verboseShutdown)
1640 LOGD("VM cleaning up\n");
1642 dvmDebuggerShutdown();
1643 dvmReflectShutdown();
1644 #ifdef WITH_PROFILER
1645 dvmProfilingShutdown();
1648 dvmStringInternShutdown();
1649 dvmExceptionShutdown();
1650 dvmThreadShutdown();
1652 dvmVerificationShutdown();
1653 dvmRegisterMapShutdown();
1654 dvmInstanceofShutdown();
1655 dvmInlineNativeShutdown();
1657 dvmAllocTrackerShutdown();
1658 dvmPropertiesShutdown();
1660 /* these must happen AFTER dvmClassShutdown has walked through class data */
1661 dvmNativeShutdown();
1662 dvmInternalNativeShutdown();
1664 free(gDvm.bootClassPathStr);
1665 free(gDvm.classPathStr);
1667 freeAssertionCtrl();
1670 * We want valgrind to report anything we forget to free as "definitely
1671 * lost". If there's a pointer in the global chunk, it would be reported
1672 * as "still reachable". Erasing the memory fixes this.
1674 * This must be erased to zero if we want to restart the VM within this
1677 memset(&gDvm, 0xcd, sizeof(gDvm));
1682 * fprintf() wrapper that calls through the JNI-specified vfprintf hook if
1683 * one was specified.
1685 int dvmFprintf(FILE* fp, const char* format, ...)
1690 va_start(args, format);
1691 if (gDvm.vfprintfHook != NULL)
1692 result = (*gDvm.vfprintfHook)(fp, format, args);
1694 result = vfprintf(fp, format, args);
1701 * Abort the VM. We get here on fatal errors. Try very hard not to use
1702 * this; whenever possible, return an error to somebody responsible.
1706 LOGE("VM aborting\n");
1708 fflush(NULL); // flush all open file buffers
1710 /* JNI-supplied abort hook gets right of first refusal */
1711 if (gDvm.abortHook != NULL)
1712 (*gDvm.abortHook)();
1715 * If we call abort(), all threads in the process receives a SIBABRT.
1716 * debuggerd dumps the stack trace of the main thread, whether or not
1717 * that was the thread that failed.
1719 * By stuffing a value into a bogus address, we cause a segmentation
1720 * fault in the current thread, and get a useful log from debuggerd.
1721 * We can also trivially tell the difference between a VM crash and
1722 * a deliberate abort by looking at the fault address.
1724 *((char*)0xdeadd00d) = 38;