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 * Currently defined in ../include/nativehelper/AndroidSystemNatives.h
42 extern int jniRegisterSystemMethods(JNIEnv* env);
45 static bool registerSystemNatives(JNIEnv* pEnv);
46 static bool dvmInitJDWP(void);
47 static bool dvmInitZygote(void);
51 struct DvmGlobals gDvm;
53 /* JIT-specific global state */
55 struct DvmJitGlobals gDvmJit;
61 * We follow the tradition of unhyphenated compound words.
63 static void dvmUsage(const char* progName)
65 dvmFprintf(stderr, "%s: [options] class [argument ...]\n", progName);
66 dvmFprintf(stderr, "%s: [options] -jar file.jar [argument ...]\n",progName);
67 dvmFprintf(stderr, "\n");
68 dvmFprintf(stderr, "The following standard options are recognized:\n");
69 dvmFprintf(stderr, " -classpath classpath\n");
70 dvmFprintf(stderr, " -Dproperty=value\n");
71 dvmFprintf(stderr, " -verbose:tag ('gc', 'jni', or 'class')\n");
72 dvmFprintf(stderr, " -ea[:<package name>... |:<class name>]\n");
73 dvmFprintf(stderr, " -da[:<package name>... |:<class name>]\n");
74 dvmFprintf(stderr, " (-enableassertions, -disableassertions)\n");
75 dvmFprintf(stderr, " -esa\n");
76 dvmFprintf(stderr, " -dsa\n");
78 " (-enablesystemassertions, -disablesystemassertions)\n");
79 dvmFprintf(stderr, " -showversion\n");
80 dvmFprintf(stderr, " -help\n");
81 dvmFprintf(stderr, "\n");
82 dvmFprintf(stderr, "The following extended options are recognized:\n");
83 dvmFprintf(stderr, " -Xrunjdwp:<options>\n");
84 dvmFprintf(stderr, " -Xbootclasspath:bootclasspath\n");
85 dvmFprintf(stderr, " -Xcheck:tag (e.g. 'jni')\n");
86 dvmFprintf(stderr, " -XmsN (min heap, must be multiple of 1K, >= 1MB)\n");
87 dvmFprintf(stderr, " -XmxN (max heap, must be multiple of 1K, >= 2MB)\n");
88 dvmFprintf(stderr, " -XssN (stack size, >= %dKB, <= %dKB)\n",
89 kMinStackSize / 1024, kMaxStackSize / 1024);
90 dvmFprintf(stderr, " -Xverify:{none,remote,all}\n");
91 dvmFprintf(stderr, " -Xrs\n");
94 " -Xint (extended to accept ':portable', ':fast' and ':jit')\n");
97 " -Xint (extended to accept ':portable' and ':fast')\n");
99 dvmFprintf(stderr, "\n");
100 dvmFprintf(stderr, "These are unique to Dalvik:\n");
101 dvmFprintf(stderr, " -Xzygote\n");
102 dvmFprintf(stderr, " -Xdexopt:{none,verified,all}\n");
103 dvmFprintf(stderr, " -Xnoquithandler\n");
105 " -Xjnigreflimit:N (must be multiple of 100, >= 200)\n");
106 dvmFprintf(stderr, " -Xjniopts:{warnonly,forcecopy}\n");
107 dvmFprintf(stderr, " -Xdeadlockpredict:{off,warn,err,abort}\n");
108 dvmFprintf(stderr, " -Xstacktracefile:<filename>\n");
109 dvmFprintf(stderr, " -Xgc:[no]precise\n");
110 dvmFprintf(stderr, " -Xgenregmap\n");
111 dvmFprintf(stderr, " -Xcheckdexsum\n");
112 #if defined(WITH_JIT)
113 dvmFprintf(stderr, " -Xincludeselectedop\n");
114 dvmFprintf(stderr, " -Xjitop:hexopvalue[-endvalue]"
115 "[,hexopvalue[-endvalue]]*\n");
116 dvmFprintf(stderr, " -Xincludeselectedmethod\n");
117 dvmFprintf(stderr, " -Xthreshold:decimalvalue\n");
118 dvmFprintf(stderr, " -Xblocking\n");
119 dvmFprintf(stderr, " -Xjitmethod:signture[,signature]* "
120 "(eg Ljava/lang/String\\;replace)\n");
121 dvmFprintf(stderr, " -Xjitverbose\n");
122 dvmFprintf(stderr, " -Xjitprofile\n");
124 dvmFprintf(stderr, "\n");
125 dvmFprintf(stderr, "Configured with:"
132 #ifdef WITH_MONITOR_TRACKING
135 #ifdef WITH_DEADLOCK_PREDICTION
136 " deadlock_prediction"
141 #ifdef WITH_HPROF_STACK
144 #ifdef WITH_HPROF_STACK_UNREACHABLE
145 " hprof_stack_unreachable"
147 #ifdef WITH_ALLOC_LIMITS
150 #ifdef WITH_TRACKREF_CHECKS
153 #ifdef WITH_INSTR_CHECKS
156 #ifdef WITH_EXTRA_OBJECT_VALIDATION
157 " extra_object_validation"
159 #ifdef WITH_EXTRA_GC_CHECKS
162 #ifdef WITH_DALVIK_ASSERT
165 #ifdef WITH_JNI_STACK_CHECK
174 #ifdef PROFILE_FIELD_ACCESS
175 " profile_field_access"
177 #ifdef DVM_TRACK_HEAP_MARKING
178 " track_heap_marking"
180 #if DVM_RESOLVER_CACHE == DVM_RC_REDUCING
181 " resolver_cache_reducing"
182 #elif DVM_RESOLVER_CACHE == DVM_RC_EXPANDING
183 " resolver_cache_expanding"
184 #elif DVM_RESOLVER_CACHE == DVM_RC_NO_CACHE
185 " resolver_cache_disabled"
187 #if defined(WITH_JIT)
191 #ifdef DVM_SHOW_EXCEPTION
192 dvmFprintf(stderr, " show_exception=%d", DVM_SHOW_EXCEPTION);
194 dvmFprintf(stderr, "\n\n");
198 * Show helpful information on JDWP options.
200 static void showJdwpHelp(void)
203 "Example: -Xrunjdwp:transport=dt_socket,address=8000,server=y\n");
205 "Example: -Xrunjdwp:transport=dt_socket,address=localhost:6500,server=n\n");
209 * Show version and copyright info.
211 static void showVersion(void)
213 dvmFprintf(stdout, "DalvikVM version %d.%d.%d\n",
214 DALVIK_MAJOR_VERSION, DALVIK_MINOR_VERSION, DALVIK_BUG_VERSION);
216 "Copyright (C) 2007 The Android Open Source Project\n\n"
217 "This software is built from source code licensed under the "
219 "Version 2.0 (the \"License\"). You may obtain a copy of the "
221 " http://www.apache.org/licenses/LICENSE-2.0\n\n"
222 "See the associated NOTICE file for this software for further "
227 * Parse a string of the form /[0-9]+[kKmMgG]?/, which is used to specify
228 * memory sizes. [kK] indicates kilobytes, [mM] megabytes, and
231 * "s" should point just past the "-Xm?" part of the string.
232 * "min" specifies the lowest acceptable value described by "s".
233 * "div" specifies a divisor, e.g. 1024 if the value must be a multiple
236 * The spec says the -Xmx and -Xms options must be multiples of 1024. It
237 * doesn't say anything about -Xss.
239 * Returns 0 (a useless size) if "s" is malformed or specifies a low or
240 * non-evenly-divisible value.
242 static unsigned int dvmParseMemOption(const char *s, unsigned int div)
244 /* strtoul accepts a leading [+-], which we don't want,
245 * so make sure our string starts with a decimal digit.
251 val = (unsigned int)strtoul(s, (char **)&s2, 10);
253 /* s2 should be pointing just after the number.
254 * If this is the end of the string, the user
255 * has specified a number of bytes. Otherwise,
256 * there should be exactly one more character
257 * that specifies a multiplier.
262 /* The remainder of the string is either a single multiplier
263 * character, or nothing to indicate that the value is in
272 } else if (c == 'k' || c == 'K') {
274 } else if (c == 'm' || c == 'M') {
276 } else if (c == 'g' || c == 'G') {
277 mul = 1024 * 1024 * 1024;
279 /* Unknown multiplier character.
284 if (val <= UINT_MAX / mul) {
287 /* Clamp to a multiple of 1024.
289 val = UINT_MAX & ~(1024-1);
292 /* There's more than one character after the
299 /* The man page says that a -Xm value must be
300 * a multiple of 1024.
302 if (val % div == 0) {
312 * Handle one of the JDWP name/value pairs.
315 * help: if specified, show help message and bail
316 * transport: may be dt_socket or dt_shmem
317 * address: for dt_socket, "host:port", or just "port" when listening
318 * server: if "y", wait for debugger to attach; if "n", attach to debugger
319 * timeout: how long to wait for debugger to connect / listen
321 * Useful with server=n (these aren't supported yet):
322 * onthrow=<exception-name>: connect to debugger when exception thrown
323 * onuncaught=y|n: connect to debugger when uncaught exception thrown
324 * launch=<command-line>: launch the debugger itself
326 * The "transport" option is required, as is "address" if server=n.
328 static bool handleJdwpOption(const char* name, const char* value)
330 if (strcmp(name, "transport") == 0) {
331 if (strcmp(value, "dt_socket") == 0) {
332 gDvm.jdwpTransport = kJdwpTransportSocket;
333 } else if (strcmp(value, "dt_android_adb") == 0) {
334 gDvm.jdwpTransport = kJdwpTransportAndroidAdb;
336 LOGE("JDWP transport '%s' not supported\n", value);
339 } else if (strcmp(name, "server") == 0) {
341 gDvm.jdwpServer = false;
342 else if (*value == 'y')
343 gDvm.jdwpServer = true;
345 LOGE("JDWP option 'server' must be 'y' or 'n'\n");
348 } else if (strcmp(name, "suspend") == 0) {
350 gDvm.jdwpSuspend = false;
351 else if (*value == 'y')
352 gDvm.jdwpSuspend = true;
354 LOGE("JDWP option 'suspend' must be 'y' or 'n'\n");
357 } else if (strcmp(name, "address") == 0) {
358 /* this is either <port> or <host>:<port> */
359 const char* colon = strchr(value, ':');
365 gDvm.jdwpHost = (char*) malloc(colon - value +1);
366 strncpy(gDvm.jdwpHost, value, colon - value +1);
367 gDvm.jdwpHost[colon-value] = '\0';
370 if (*value == '\0') {
371 LOGE("JDWP address missing port\n");
374 port = strtol(value, &end, 10);
376 LOGE("JDWP address has junk in port field '%s'\n", value);
379 gDvm.jdwpPort = port;
380 } else if (strcmp(name, "launch") == 0 ||
381 strcmp(name, "onthrow") == 0 ||
382 strcmp(name, "oncaught") == 0 ||
383 strcmp(name, "timeout") == 0)
385 /* valid but unsupported */
386 LOGI("Ignoring JDWP option '%s'='%s'\n", name, value);
388 LOGI("Ignoring unrecognized JDWP option '%s'='%s'\n", name, value);
395 * Parse the latter half of a -Xrunjdwp/-agentlib:jdwp= string, e.g.:
396 * "transport=dt_socket,address=8000,server=y,suspend=n"
398 static bool parseJdwpOptions(const char* str)
400 char* mangle = strdup(str);
405 * Process all of the name=value pairs.
411 value = strchr(name, '=');
413 LOGE("JDWP opts: garbage at '%s'\n", name);
417 comma = strchr(name, ','); // use name, not value, for safety
420 LOGE("JDWP opts: found comma before '=' in '%s'\n", mangle);
426 *value++ = '\0'; // stomp the '='
428 if (!handleJdwpOption(name, value))
439 * Make sure the combination of arguments makes sense.
441 if (gDvm.jdwpTransport == kJdwpTransportUnknown) {
442 LOGE("JDWP opts: must specify transport\n");
445 if (!gDvm.jdwpServer && (gDvm.jdwpHost == NULL || gDvm.jdwpPort == 0)) {
446 LOGE("JDWP opts: when server=n, must specify host and port\n");
449 // transport mandatory
450 // outbound server address
452 gDvm.jdwpConfigured = true;
461 * Handle one of the four kinds of assertion arguments.
463 * "pkgOrClass" is the last part of an enable/disable line. For a package
464 * the arg looks like "-ea:com.google.fubar...", for a class it looks
465 * like "-ea:com.google.fubar.Wahoo". The string we get starts at the ':'.
467 * For system assertions (-esa/-dsa), "pkgOrClass" is NULL.
469 * Multiple instances of these arguments can be specified, e.g. you can
470 * enable assertions for a package and then disable them for one class in
473 static bool enableAssertions(const char* pkgOrClass, bool enable)
475 AssertionControl* pCtrl = &gDvm.assertionCtrl[gDvm.assertionCtrlCount++];
476 pCtrl->enable = enable;
478 if (pkgOrClass == NULL) {
479 /* enable or disable for all system classes */
480 pCtrl->isPackage = false;
481 pCtrl->pkgOrClass = NULL;
482 pCtrl->pkgOrClassLen = 0;
484 if (*pkgOrClass == '\0') {
485 /* global enable/disable for all but system */
486 pCtrl->isPackage = false;
487 pCtrl->pkgOrClass = strdup("");
488 pCtrl->pkgOrClassLen = 0;
490 pCtrl->pkgOrClass = dvmDotToSlash(pkgOrClass+1); // skip ':'
491 if (pCtrl->pkgOrClass == NULL) {
492 /* can happen if class name includes an illegal '/' */
493 LOGW("Unable to process assertion arg '%s'\n", pkgOrClass);
497 int len = strlen(pCtrl->pkgOrClass);
498 if (len >= 3 && strcmp(pCtrl->pkgOrClass + len-3, "///") == 0) {
499 /* mark as package, truncate two of the three slashes */
500 pCtrl->isPackage = true;
501 *(pCtrl->pkgOrClass + len-2) = '\0';
502 pCtrl->pkgOrClassLen = len - 2;
505 pCtrl->isPackage = false;
506 pCtrl->pkgOrClassLen = len;
515 * Turn assertions on when requested to do so by the Zygote.
517 * This is a bit sketchy. We can't (easily) go back and fiddle with all
518 * of the classes that have already been initialized, so this only
519 * affects classes that have yet to be loaded. If some or all assertions
520 * have been enabled through some other means, we don't want to mess with
521 * it here, so we do nothing. Finally, we assume that there's room in
522 * "assertionCtrl" to hold at least one entry; this is guaranteed by the
525 * This must only be called from the main thread during zygote init.
527 void dvmLateEnableAssertions(void)
529 if (gDvm.assertionCtrl == NULL) {
530 LOGD("Not late-enabling assertions: no assertionCtrl array\n");
532 } else if (gDvm.assertionCtrlCount != 0) {
533 LOGD("Not late-enabling assertions: some asserts already configured\n");
536 LOGD("Late-enabling assertions\n");
538 /* global enable for all but system */
539 AssertionControl* pCtrl = gDvm.assertionCtrl;
540 pCtrl->pkgOrClass = strdup("");
541 pCtrl->pkgOrClassLen = 0;
542 pCtrl->isPackage = false;
543 pCtrl->enable = true;
544 gDvm.assertionCtrlCount = 1;
549 * Release memory associated with the AssertionCtrl array.
551 static void freeAssertionCtrl(void)
555 for (i = 0; i < gDvm.assertionCtrlCount; i++)
556 free(gDvm.assertionCtrl[i].pkgOrClass);
557 free(gDvm.assertionCtrl);
560 #if defined(WITH_JIT)
561 /* Parse -Xjitop to selectively turn on/off certain opcodes for JIT */
562 static void processXjitop(const char *opt)
565 const char *startPtr = &opt[8];
569 long startValue, endValue;
571 startValue = strtol(startPtr, &endPtr, 16);
572 if (startPtr != endPtr) {
573 /* Just in case value is out of range */
576 if (*endPtr == '-') {
577 endValue = strtol(endPtr+1, &endPtr, 16);
580 endValue = startValue;
583 for (; startValue <= endValue; startValue++) {
584 LOGW("Dalvik opcode %x is selected for debugging",
585 (unsigned int) startValue);
586 /* Mark the corresponding bit to 1 */
587 gDvmJit.opList[startValue >> 3] |=
588 1 << (startValue & 0x7);
595 startPtr = endPtr + 1;
601 "Warning: Unrecognized opcode value substring "
609 for (i = 0; i < 32; i++) {
610 gDvmJit.opList[i] = 0xff;
612 dvmFprintf(stderr, "Warning: select all opcodes\n");
616 /* Parse -Xjitmethod to selectively turn on/off certain methods for JIT */
617 static void processXjitmethod(const char *opt)
619 char *buf = strdup(&opt[12]);
622 gDvmJit.methodTable = dvmHashTableCreate(8, NULL);
626 * Break comma-separated method signatures and enter them into the hash
627 * table individually.
632 end = strchr(start, ',');
637 hashValue = dvmComputeUtf8Hash(start);
639 dvmHashTableLookup(gDvmJit.methodTable, hashValue,
641 (HashCompareFunc) strcmp, true);
653 * Process an argument vector full of options. Unlike standard C programs,
654 * argv[0] does not contain the name of the program.
656 * If "ignoreUnrecognized" is set, we ignore options starting with "-X" or "_"
657 * that we don't recognize. Otherwise, we return with an error as soon as
658 * we see anything we can't identify.
660 * Returns 0 on success, -1 on failure, and 1 for the special case of
661 * "-version" where we want to stop without showing an error message.
663 static int dvmProcessOptions(int argc, const char* const argv[],
664 bool ignoreUnrecognized)
668 LOGV("VM options (%d):\n", argc);
669 for (i = 0; i < argc; i++)
670 LOGV(" %d: '%s'\n", i, argv[i]);
673 * Over-allocate AssertionControl array for convenience. If allocated,
674 * the array must be able to hold at least one entry, so that the
675 * zygote-time activation can do its business.
677 assert(gDvm.assertionCtrl == NULL);
680 (AssertionControl*) malloc(sizeof(AssertionControl) * argc);
681 if (gDvm.assertionCtrl == NULL)
683 assert(gDvm.assertionCtrlCount == 0);
686 for (i = 0; i < argc; i++) {
687 if (strcmp(argv[i], "-help") == 0) {
688 /* show usage and stop */
691 } else if (strcmp(argv[i], "-version") == 0) {
692 /* show version and stop */
695 } else if (strcmp(argv[i], "-showversion") == 0) {
696 /* show version and continue */
699 } else if (strcmp(argv[i], "-classpath") == 0 ||
700 strcmp(argv[i], "-cp") == 0)
704 dvmFprintf(stderr, "Missing classpath path list\n");
707 free(gDvm.classPathStr); /* in case we have compiled-in default */
708 gDvm.classPathStr = strdup(argv[++i]);
710 } else if (strncmp(argv[i], "-Xbootclasspath:",
711 sizeof("-Xbootclasspath:")-1) == 0)
713 /* set bootclasspath */
714 const char* path = argv[i] + sizeof("-Xbootclasspath:")-1;
717 dvmFprintf(stderr, "Missing bootclasspath path list\n");
720 free(gDvm.bootClassPathStr);
721 gDvm.bootClassPathStr = strdup(path);
724 * TODO: support -Xbootclasspath/a and /p, which append or
725 * prepend to the default bootclasspath. We set the default
729 } else if (strncmp(argv[i], "-D", 2) == 0) {
731 dvmAddCommandLineProperty(argv[i] + 2);
733 } else if (strcmp(argv[i], "-jar") == 0) {
734 // TODO: handle this; name of jar should be in argv[i+1]
735 dvmFprintf(stderr, "-jar not yet handled\n");
738 } else if (strncmp(argv[i], "-Xms", 4) == 0) {
739 unsigned int val = dvmParseMemOption(argv[i]+4, 1024);
741 if (val >= kMinHeapStartSize && val <= kMaxHeapSize) {
742 gDvm.heapSizeStart = val;
745 "Invalid -Xms '%s', range is %dKB to %dKB\n",
746 argv[i], kMinHeapStartSize/1024, kMaxHeapSize/1024);
750 dvmFprintf(stderr, "Invalid -Xms option '%s'\n", argv[i]);
753 } else if (strncmp(argv[i], "-Xmx", 4) == 0) {
754 unsigned int val = dvmParseMemOption(argv[i]+4, 1024);
756 if (val >= kMinHeapSize && val <= kMaxHeapSize) {
757 gDvm.heapSizeMax = val;
760 "Invalid -Xmx '%s', range is %dKB to %dKB\n",
761 argv[i], kMinHeapSize/1024, kMaxHeapSize/1024);
765 dvmFprintf(stderr, "Invalid -Xmx option '%s'\n", argv[i]);
768 } else if (strncmp(argv[i], "-Xss", 4) == 0) {
769 unsigned int val = dvmParseMemOption(argv[i]+4, 1);
771 if (val >= kMinStackSize && val <= kMaxStackSize) {
772 gDvm.stackSize = val;
774 dvmFprintf(stderr, "Invalid -Xss '%s', range is %d to %d\n",
775 argv[i], kMinStackSize, kMaxStackSize);
779 dvmFprintf(stderr, "Invalid -Xss option '%s'\n", argv[i]);
783 } else if (strcmp(argv[i], "-verbose") == 0 ||
784 strcmp(argv[i], "-verbose:class") == 0)
786 // JNI spec says "-verbose:gc,class" is valid, but cmd line
787 // doesn't work that way; may want to support.
788 gDvm.verboseClass = true;
789 } else if (strcmp(argv[i], "-verbose:jni") == 0) {
790 gDvm.verboseJni = true;
791 } else if (strcmp(argv[i], "-verbose:gc") == 0) {
792 gDvm.verboseGc = true;
794 } else if (strncmp(argv[i], "-enableassertions", 17) == 0) {
795 enableAssertions(argv[i] + 17, true);
796 } else if (strncmp(argv[i], "-ea", 3) == 0) {
797 enableAssertions(argv[i] + 3, true);
798 } else if (strncmp(argv[i], "-disableassertions", 18) == 0) {
799 enableAssertions(argv[i] + 18, false);
800 } else if (strncmp(argv[i], "-da", 3) == 0) {
801 enableAssertions(argv[i] + 3, false);
802 } else if (strcmp(argv[i], "-enablesystemassertions") == 0 ||
803 strcmp(argv[i], "-esa") == 0)
805 enableAssertions(NULL, true);
806 } else if (strcmp(argv[i], "-disablesystemassertions") == 0 ||
807 strcmp(argv[i], "-dsa") == 0)
809 enableAssertions(NULL, false);
811 } else if (strncmp(argv[i], "-Xcheck:jni", 11) == 0) {
812 /* nothing to do now -- was handled during JNI init */
814 } else if (strcmp(argv[i], "-Xdebug") == 0) {
815 /* accept but ignore */
817 } else if (strncmp(argv[i], "-Xrunjdwp:", 10) == 0 ||
818 strncmp(argv[i], "-agentlib:jdwp=", 15) == 0)
823 if (argv[i][1] == 'X')
828 if (strncmp(tail, "help", 4) == 0 || !parseJdwpOptions(tail)) {
832 } else if (strcmp(argv[i], "-Xrs") == 0) {
833 gDvm.reduceSignals = true;
834 } else if (strcmp(argv[i], "-Xnoquithandler") == 0) {
835 /* disables SIGQUIT handler thread while still blocking SIGQUIT */
836 /* (useful if we don't want thread but system still signals us) */
837 gDvm.noQuitHandler = true;
838 } else if (strcmp(argv[i], "-Xzygote") == 0) {
840 } else if (strncmp(argv[i], "-Xdexopt:", 9) == 0) {
841 if (strcmp(argv[i] + 9, "none") == 0)
842 gDvm.dexOptMode = OPTIMIZE_MODE_NONE;
843 else if (strcmp(argv[i] + 9, "verified") == 0)
844 gDvm.dexOptMode = OPTIMIZE_MODE_VERIFIED;
845 else if (strcmp(argv[i] + 9, "all") == 0)
846 gDvm.dexOptMode = OPTIMIZE_MODE_ALL;
848 dvmFprintf(stderr, "Unrecognized dexopt option '%s'\n",argv[i]);
851 } else if (strncmp(argv[i], "-Xverify:", 9) == 0) {
852 if (strcmp(argv[i] + 9, "none") == 0)
853 gDvm.classVerifyMode = VERIFY_MODE_NONE;
854 else if (strcmp(argv[i] + 9, "remote") == 0)
855 gDvm.classVerifyMode = VERIFY_MODE_REMOTE;
856 else if (strcmp(argv[i] + 9, "all") == 0)
857 gDvm.classVerifyMode = VERIFY_MODE_ALL;
859 dvmFprintf(stderr, "Unrecognized verify option '%s'\n",argv[i]);
862 } else if (strncmp(argv[i], "-Xjnigreflimit:", 15) == 0) {
863 int lim = atoi(argv[i] + 15);
864 if (lim < 200 || (lim % 100) != 0) {
865 dvmFprintf(stderr, "Bad value for -Xjnigreflimit: '%s'\n",
869 gDvm.jniGrefLimit = lim;
871 } else if (strcmp(argv[i], "-Xlog-stdio") == 0) {
872 gDvm.logStdio = true;
874 } else if (strncmp(argv[i], "-Xint", 5) == 0) {
875 if (argv[i][5] == ':') {
876 if (strcmp(argv[i] + 6, "portable") == 0)
877 gDvm.executionMode = kExecutionModeInterpPortable;
878 else if (strcmp(argv[i] + 6, "fast") == 0)
879 gDvm.executionMode = kExecutionModeInterpFast;
881 else if (strcmp(argv[i] + 6, "jit") == 0)
882 gDvm.executionMode = kExecutionModeJit;
886 "Warning: Unrecognized interpreter mode %s\n",argv[i]);
890 /* disable JIT -- nothing to do here for now */
894 } else if (strncmp(argv[i], "-Xjitop", 7) == 0) {
895 processXjitop(argv[i]);
896 } else if (strncmp(argv[i], "-Xjitmethod", 11) == 0) {
897 processXjitmethod(argv[i]);
898 } else if (strncmp(argv[i], "-Xblocking", 10) == 0) {
899 gDvmJit.blockingMode = true;
900 } else if (strncmp(argv[i], "-Xthreshold:", 12) == 0) {
901 gDvmJit.threshold = atoi(argv[i] + 12);
902 } else if (strncmp(argv[i], "-Xincludeselectedop", 19) == 0) {
903 gDvmJit.includeSelectedOp = true;
904 } else if (strncmp(argv[i], "-Xincludeselectedmethod", 23) == 0) {
905 gDvmJit.includeSelectedMethod = true;
906 } else if (strncmp(argv[i], "-Xjitverbose", 12) == 0) {
907 gDvmJit.printMe = true;
908 } else if (strncmp(argv[i], "-Xjitprofile", 12) == 0) {
909 gDvmJit.profile = true;
912 } else if (strncmp(argv[i], "-Xdeadlockpredict:", 18) == 0) {
913 #ifdef WITH_DEADLOCK_PREDICTION
914 if (strcmp(argv[i] + 18, "off") == 0)
915 gDvm.deadlockPredictMode = kDPOff;
916 else if (strcmp(argv[i] + 18, "warn") == 0)
917 gDvm.deadlockPredictMode = kDPWarn;
918 else if (strcmp(argv[i] + 18, "err") == 0)
919 gDvm.deadlockPredictMode = kDPErr;
920 else if (strcmp(argv[i] + 18, "abort") == 0)
921 gDvm.deadlockPredictMode = kDPAbort;
923 dvmFprintf(stderr, "Bad value for -Xdeadlockpredict");
926 if (gDvm.deadlockPredictMode != kDPOff)
927 LOGD("Deadlock prediction enabled (%s)\n", argv[i]+18);
930 } else if (strncmp(argv[i], "-Xstacktracefile:", 17) == 0) {
931 gDvm.stackTraceFile = strdup(argv[i]+17);
933 } else if (strcmp(argv[i], "-Xgenregmap") == 0) {
934 gDvm.generateRegisterMaps = true;
935 LOGV("Register maps will be generated during verification\n");
937 } else if (strncmp(argv[i], "-Xgc:", 5) == 0) {
938 if (strcmp(argv[i] + 5, "precise") == 0)
939 gDvm.preciseGc = true;
940 else if (strcmp(argv[i] + 5, "noprecise") == 0)
941 gDvm.preciseGc = false;
943 dvmFprintf(stderr, "Bad value for -Xgc");
946 LOGD("Precise GC configured %s\n", gDvm.preciseGc ? "ON" : "OFF");
948 } else if (strcmp(argv[i], "-Xcheckdexsum") == 0) {
949 gDvm.verifyDexChecksum = true;
952 if (!ignoreUnrecognized) {
953 dvmFprintf(stderr, "Unrecognized option '%s'\n", argv[i]);
959 if (gDvm.heapSizeStart > gDvm.heapSizeMax) {
960 dvmFprintf(stderr, "Heap start size must be <= heap max size\n");
968 * Set defaults for fields altered or modified by arguments.
970 * Globals are initialized to 0 (a/k/a NULL or false).
972 static void setCommandLineDefaults()
976 envStr = getenv("CLASSPATH");
978 gDvm.classPathStr = strdup(envStr);
980 gDvm.classPathStr = strdup(".");
981 envStr = getenv("BOOTCLASSPATH");
983 gDvm.bootClassPathStr = strdup(envStr);
985 gDvm.bootClassPathStr = strdup(".");
987 /* Defaults overridden by -Xms and -Xmx.
988 * TODO: base these on a system or application-specific default
990 gDvm.heapSizeStart = 2 * 1024 * 1024; // Spec says 16MB; too big for us.
991 gDvm.heapSizeMax = 16 * 1024 * 1024; // Spec says 75% physical mem
992 gDvm.stackSize = kDefaultStackSize;
994 /* gDvm.jdwpSuspend = true; */
996 /* allowed unless zygote config doesn't allow it */
997 gDvm.jdwpAllowed = true;
999 /* default verification and optimization modes */
1000 gDvm.classVerifyMode = VERIFY_MODE_ALL;
1001 gDvm.dexOptMode = OPTIMIZE_MODE_VERIFIED;
1004 * Default execution mode.
1006 * This should probably interact with the mterp code somehow, e.g. if
1007 * we know we're using the "desktop" build we should probably be
1008 * using "portable" rather than "fast".
1010 #if defined(WITH_JIT)
1011 gDvm.executionMode = kExecutionModeJit;
1013 * TODO - check system property and insert command-line options in
1014 * frameworks/base/core/jni/AndroidRuntime.cpp
1016 gDvmJit.blockingMode = false;
1017 gDvmJit.jitTableSize = 512;
1018 gDvmJit.jitTableMask = gDvmJit.jitTableSize - 1;
1019 gDvmJit.threshold = 200;
1021 gDvm.executionMode = kExecutionModeInterpFast;
1027 * Handle a SIGBUS, which frequently occurs because somebody replaced an
1028 * optimized DEX file out from under us.
1030 static void busCatcher(int signum, siginfo_t* info, void* context)
1032 void* addr = info->si_addr;
1034 LOGE("Caught a SIGBUS (%d), addr=%p\n", signum, addr);
1037 * If we return at this point the SIGBUS just keeps happening, so we
1038 * remove the signal handler and allow it to kill us. TODO: restore
1039 * the original, which points to a debuggerd stub; if we don't then
1040 * debuggerd won't be notified.
1042 signal(SIGBUS, SIG_DFL);
1046 * Configure signals. We need to block SIGQUIT so that the signal only
1047 * reaches the dump-stack-trace thread.
1049 * This can be disabled with the "-Xrs" flag.
1051 static void blockSignals()
1057 sigaddset(&mask, SIGQUIT);
1058 sigaddset(&mask, SIGUSR1); // used to initiate heap dump
1059 #if defined(WITH_JIT) && defined(WITH_JIT_TUNING)
1060 sigaddset(&mask, SIGUSR2); // used to investigate JIT internals
1062 //sigaddset(&mask, SIGPIPE);
1063 cc = sigprocmask(SIG_BLOCK, &mask, NULL);
1067 /* TODO: save the old sigaction in a global */
1068 struct sigaction sa;
1069 memset(&sa, 0, sizeof(sa));
1070 sa.sa_sigaction = busCatcher;
1071 sa.sa_flags = SA_SIGINFO;
1072 cc = sigaction(SIGBUS, &sa, NULL);
1078 * VM initialization. Pass in any options provided on the command line.
1079 * Do not pass in the class name or the options for the class.
1081 * Returns 0 on success.
1083 int dvmStartup(int argc, const char* const argv[], bool ignoreUnrecognized,
1088 assert(gDvm.initializing);
1090 LOGV("VM init args (%d):\n", argc);
1091 for (i = 0; i < argc; i++)
1092 LOGV(" %d: '%s'\n", i, argv[i]);
1094 setCommandLineDefaults();
1096 /* prep properties storage */
1097 if (!dvmPropertiesStartup(argc))
1101 * Process the option flags (if any).
1103 cc = dvmProcessOptions(argc, argv, ignoreUnrecognized);
1106 dvmFprintf(stderr, "\n");
1107 dvmUsage("dalvikvm");
1112 #if WITH_EXTRA_GC_CHECKS > 1
1113 /* only "portable" interp has the extra goodies */
1114 if (gDvm.executionMode != kExecutionModeInterpPortable) {
1115 LOGI("Switching to 'portable' interpreter for GC checks\n");
1116 gDvm.executionMode = kExecutionModeInterpPortable;
1120 /* Configure group scheduling capabilities */
1121 if (!access("/dev/cpuctl/tasks", F_OK)) {
1122 LOGV("Using kernel group scheduling");
1123 gDvm.kernelGroupScheduling = 1;
1125 LOGV("Using kernel scheduler policies");
1128 /* configure signal handling */
1129 if (!gDvm.reduceSignals)
1133 LOGV("Using executionMode %d\n", gDvm.executionMode);
1134 dvmCheckAsmConstants();
1137 * Initialize components.
1139 if (!dvmAllocTrackerStartup())
1141 if (!dvmGcStartup())
1143 if (!dvmThreadStartup())
1145 if (!dvmInlineNativeStartup())
1147 if (!dvmVerificationStartup())
1149 if (!dvmRegisterMapStartup())
1151 if (!dvmInstanceofStartup())
1153 if (!dvmClassStartup())
1155 if (!dvmThreadObjStartup())
1157 if (!dvmExceptionStartup())
1159 if (!dvmStringInternStartup())
1161 if (!dvmNativeStartup())
1163 if (!dvmInternalNativeStartup())
1165 if (!dvmJniStartup())
1167 if (!dvmReflectStartup())
1169 #ifdef WITH_PROFILER
1170 if (!dvmProfilingStartup())
1174 /* make sure we got these [can this go away?] */
1175 assert(gDvm.classJavaLangClass != NULL);
1176 assert(gDvm.classJavaLangObject != NULL);
1177 //assert(gDvm.classJavaLangString != NULL);
1178 assert(gDvm.classJavaLangThread != NULL);
1179 assert(gDvm.classJavaLangVMThread != NULL);
1180 assert(gDvm.classJavaLangThreadGroup != NULL);
1183 * Make sure these exist. If they don't, we can return a failure out
1184 * of main and nip the whole thing in the bud.
1186 static const char* earlyClasses[] = {
1187 "Ljava/lang/InternalError;",
1188 "Ljava/lang/StackOverflowError;",
1189 "Ljava/lang/UnsatisfiedLinkError;",
1190 "Ljava/lang/NoClassDefFoundError;",
1193 const char** pClassName;
1194 for (pClassName = earlyClasses; *pClassName != NULL; pClassName++) {
1195 if (dvmFindSystemClassNoInit(*pClassName) == NULL)
1200 * Miscellaneous class library validation.
1202 if (!dvmValidateBoxClasses())
1206 * Do the last bits of Thread struct initialization we need to allow
1207 * JNI calls to work.
1209 if (!dvmPrepMainForJni(pEnv))
1213 * Register the system native methods, which are registered through JNI.
1215 if (!registerSystemNatives(pEnv))
1219 * Do some "late" initialization for the memory allocator. This may
1220 * allocate storage and initialize classes.
1222 if (!dvmCreateStockExceptions())
1226 * At this point, the VM is in a pretty good state. Finish prep on
1227 * the main thread (specifically, create a java.lang.Thread object to go
1228 * along with our Thread struct). Note we will probably be executing
1229 * some interpreted class initializer code in here.
1231 if (!dvmPrepMainThread())
1234 /* general debugging setup */
1235 if (!dvmDebuggerStartup())
1239 * Init for either zygote mode or non-zygote mode. The key difference
1240 * is that we don't start any additional threads in Zygote mode.
1243 if (!dvmInitZygote())
1246 if (!dvmInitAfterZygote())
1253 LOGE("dmvTestHash FAILED\n");
1254 if (false /*noisy!*/ && !dvmTestIndirectRefTable())
1255 LOGE("dvmTestIndirectRefTable FAILED\n");
1258 assert(!dvmCheckException(dvmThreadSelf()));
1259 gDvm.initExceptionCount = 0;
1269 * Register java.* natives from our class libraries. We need to do
1270 * this after we're ready for JNI registration calls, but before we
1271 * do any class initialization.
1273 * If we get this wrong, we will blow up in the ThreadGroup class init if
1274 * interpreted code makes any reference to System. It will likely do this
1275 * since it wants to do some java.io.File setup (e.g. for static in/out/err).
1277 * We need to have gDvm.initializing raised here so that JNI FindClass
1278 * won't try to use the system/application class loader.
1280 static bool registerSystemNatives(JNIEnv* pEnv)
1284 /* main thread is always first in list */
1285 self = gDvm.threadList;
1287 /* must set this before allowing JNI-based method registration */
1288 self->status = THREAD_NATIVE;
1290 if (jniRegisterSystemMethods(pEnv) < 0) {
1291 LOGW("jniRegisterSystemMethods failed\n");
1295 /* back to run mode */
1296 self->status = THREAD_RUNNING;
1303 * Do zygote-mode-only initialization.
1305 static bool dvmInitZygote(void)
1307 /* zygote goes into its own process group */
1314 * Do non-zygote-mode initialization. This is done during VM init for
1315 * standard startup, or after a "zygote fork" when creating a new process.
1317 bool dvmInitAfterZygote(void)
1319 u8 startHeap, startQuit, startJdwp;
1320 u8 endHeap, endQuit, endJdwp;
1322 startHeap = dvmGetRelativeTimeUsec();
1325 * Post-zygote heap initialization, including starting
1326 * the HeapWorker thread.
1328 if (!dvmGcStartupAfterZygote())
1331 endHeap = dvmGetRelativeTimeUsec();
1332 startQuit = dvmGetRelativeTimeUsec();
1334 /* start signal catcher thread that dumps stacks on SIGQUIT */
1335 if (!gDvm.reduceSignals && !gDvm.noQuitHandler) {
1336 if (!dvmSignalCatcherStartup())
1340 /* start stdout/stderr copier, if requested */
1341 if (gDvm.logStdio) {
1342 if (!dvmStdioConverterStartup())
1346 endQuit = dvmGetRelativeTimeUsec();
1347 startJdwp = dvmGetRelativeTimeUsec();
1350 * Start JDWP thread. If the command-line debugger flags specified
1351 * "suspend=y", this will pause the VM. We probably want this to
1354 if (!dvmInitJDWP()) {
1355 LOGD("JDWP init failed; continuing anyway\n");
1358 endJdwp = dvmGetRelativeTimeUsec();
1360 LOGV("thread-start heap=%d quit=%d jdwp=%d total=%d usec\n",
1361 (int)(endHeap-startHeap), (int)(endQuit-startQuit),
1362 (int)(endJdwp-startJdwp), (int)(endJdwp-startHeap));
1365 if (!dvmJitStartup())
1373 * Prepare for a connection to a JDWP-compliant debugger.
1375 * Note this needs to happen fairly late in the startup process, because
1376 * we need to have all of the java.* native methods registered (which in
1377 * turn requires JNI to be fully prepped).
1379 * There are several ways to initialize:
1381 * We immediately try to connect to host:port. Bail on failure. On
1382 * success, send VM_START (suspending the VM if "suspend=y").
1383 * server=y suspend=n
1384 * Passively listen for a debugger to connect. Return immediately.
1385 * server=y suspend=y
1386 * Wait until debugger connects. Send VM_START ASAP, suspending the
1387 * VM after the message is sent.
1389 * This gets more complicated with a nonzero value for "timeout".
1391 static bool dvmInitJDWP(void)
1393 assert(!gDvm.zygote);
1395 #ifndef WITH_DEBUGGER
1396 LOGI("Debugger support not compiled into VM\n");
1401 * Init JDWP if the debugger is enabled. This may connect out to a
1402 * debugger, passively listen for a debugger, or block waiting for a
1405 if (gDvm.jdwpAllowed && gDvm.jdwpConfigured) {
1406 JdwpStartupParams params;
1408 if (gDvm.jdwpHost != NULL) {
1409 if (strlen(gDvm.jdwpHost) >= sizeof(params.host)-1) {
1410 LOGE("ERROR: hostname too long: '%s'\n", gDvm.jdwpHost);
1413 strcpy(params.host, gDvm.jdwpHost);
1415 params.host[0] = '\0';
1417 params.transport = gDvm.jdwpTransport;
1418 params.server = gDvm.jdwpServer;
1419 params.suspend = gDvm.jdwpSuspend;
1420 params.port = gDvm.jdwpPort;
1422 gDvm.jdwpState = dvmJdwpStartup(¶ms);
1423 if (gDvm.jdwpState == NULL) {
1424 LOGW("WARNING: debugger thread failed to initialize\n");
1425 /* TODO: ignore? fail? need to mimic "expected" behavior */
1430 * If a debugger has already attached, send the "welcome" message. This
1431 * may cause us to suspend all threads.
1433 if (dvmJdwpIsActive(gDvm.jdwpState)) {
1434 //dvmChangeStatus(NULL, THREAD_RUNNING);
1435 if (!dvmJdwpPostVMStart(gDvm.jdwpState, gDvm.jdwpSuspend)) {
1436 LOGW("WARNING: failed to post 'start' message to debugger\n");
1439 //dvmChangeStatus(NULL, THREAD_NATIVE);
1446 * An alternative to JNI_CreateJavaVM/dvmStartup that does the first bit
1447 * of initialization and then returns with "initializing" still set. (Used
1448 * by DexOpt command-line utility.)
1450 * Attempting to use JNI or internal natives will fail. It's best if
1451 * no bytecode gets executed, which means no <clinit>, which means no
1452 * exception-throwing. We check the "initializing" flag anyway when
1453 * throwing an exception, so we can insert some code that avoids chucking
1454 * an exception when we're optimizing stuff.
1456 * Returns 0 on success.
1458 int dvmPrepForDexOpt(const char* bootClassPath, DexOptimizerMode dexOptMode,
1459 DexClassVerifyMode verifyMode, int dexoptFlags)
1461 gDvm.initializing = true;
1462 gDvm.optimizing = true;
1464 /* configure signal handling */
1467 /* set some defaults */
1468 setCommandLineDefaults();
1469 free(gDvm.bootClassPathStr);
1470 gDvm.bootClassPathStr = strdup(bootClassPath);
1472 /* set opt/verify modes */
1473 gDvm.dexOptMode = dexOptMode;
1474 gDvm.classVerifyMode = verifyMode;
1475 gDvm.generateRegisterMaps = (dexoptFlags & DEXOPT_GEN_REGISTER_MAPS) != 0;
1478 * Initialize the heap, some basic thread control mutexes, and
1479 * get the bootclasspath prepped.
1481 * We can't load any classes yet because we may not yet have a source
1482 * for things like java.lang.Object and java.lang.Class.
1484 if (!dvmGcStartup())
1486 if (!dvmThreadStartup())
1488 if (!dvmInlineNativeStartup())
1490 if (!dvmVerificationStartup())
1492 if (!dvmRegisterMapStartup())
1494 if (!dvmInstanceofStartup())
1496 if (!dvmClassStartup())
1500 * We leave gDvm.initializing set to "true" so that, if we're not
1501 * able to process the "core" classes, we don't go into a death-spin
1502 * trying to throw a "class not found" exception.
1514 * All threads have stopped. Finish the shutdown procedure.
1516 * We can also be called if startup fails partway through, so be prepared
1517 * to deal with partially initialized data.
1519 * Free any storage allocated in gGlobals.
1521 * We can't dlclose() shared libs we've loaded, because it's possible a
1522 * thread not associated with the VM is running code in one.
1524 * This is called from the JNI DestroyJavaVM function, which can be
1525 * called from any thread. (In practice, this will usually run in the
1526 * same thread that started the VM, a/k/a the main thread, but we don't
1527 * want to assume that.)
1529 void dvmShutdown(void)
1531 LOGV("VM shutting down\n");
1533 if (CALC_CACHE_STATS)
1534 dvmDumpAtomicCacheStats(gDvm.instanceofCache);
1537 * Stop our internal threads.
1539 dvmHeapWorkerShutdown();
1541 if (gDvm.jdwpState != NULL)
1542 dvmJdwpShutdown(gDvm.jdwpState);
1543 free(gDvm.jdwpHost);
1544 gDvm.jdwpHost = NULL;
1545 free(gDvm.stackTraceFile);
1546 gDvm.stackTraceFile = NULL;
1548 /* tell signal catcher to shut down if it was started */
1549 dvmSignalCatcherShutdown();
1551 /* shut down stdout/stderr conversion */
1552 dvmStdioConverterShutdown();
1555 /* tell the compiler to shut down if it was started */
1560 * Kill any daemon threads that still exist. Actively-running threads
1561 * are likely to crash the process if they continue to execute while
1562 * the VM shuts down.
1566 LOGD("VM cleaning up\n");
1568 dvmDebuggerShutdown();
1569 dvmReflectShutdown();
1570 #ifdef WITH_PROFILER
1571 dvmProfilingShutdown();
1574 dvmStringInternShutdown();
1575 dvmExceptionShutdown();
1576 dvmThreadShutdown();
1578 dvmVerificationShutdown();
1579 dvmRegisterMapShutdown();
1580 dvmInstanceofShutdown();
1581 dvmInlineNativeShutdown();
1583 dvmAllocTrackerShutdown();
1584 dvmPropertiesShutdown();
1586 /* these must happen AFTER dvmClassShutdown has walked through class data */
1587 dvmNativeShutdown();
1588 dvmInternalNativeShutdown();
1590 free(gDvm.bootClassPathStr);
1591 free(gDvm.classPathStr);
1593 freeAssertionCtrl();
1596 * We want valgrind to report anything we forget to free as "definitely
1597 * lost". If there's a pointer in the global chunk, it would be reported
1598 * as "still reachable". Erasing the memory fixes this.
1600 * This must be erased to zero if we want to restart the VM within this
1603 memset(&gDvm, 0xcd, sizeof(gDvm));
1608 * fprintf() wrapper that calls through the JNI-specified vfprintf hook if
1609 * one was specified.
1611 int dvmFprintf(FILE* fp, const char* format, ...)
1616 va_start(args, format);
1617 if (gDvm.vfprintfHook != NULL)
1618 result = (*gDvm.vfprintfHook)(fp, format, args);
1620 result = vfprintf(fp, format, args);
1627 * Abort the VM. We get here on fatal errors. Try very hard not to use
1628 * this; whenever possible, return an error to somebody responsible.
1632 LOGE("VM aborting\n");
1634 fflush(NULL); // flush all open file buffers
1636 /* JNI-supplied abort hook gets right of first refusal */
1637 if (gDvm.abortHook != NULL)
1638 (*gDvm.abortHook)();
1641 * If we call abort(), all threads in the process receives a SIBABRT.
1642 * debuggerd dumps the stack trace of the main thread, whether or not
1643 * that was the thread that failed.
1645 * By stuffing a value into a bogus address, we cause a segmentation
1646 * fault in the current thread, and get a useful log from debuggerd.
1647 * We can also trivially tell the difference between a VM crash and
1648 * a deliberate abort by looking at the fault address.
1650 *((char*)0xdeadd00d) = 38;