blob: 629a50a64992f07b002880b81df269e7f700bd37 [file] [log] [blame]
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16
17/*
18 * Dalvik initialization, shutdown, and command-line argument processing.
19 */
Carl Shapirod5c36b92011-04-15 18:38:06 -070020#define __STDC_LIMIT_MACROS
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080021#include <stdlib.h>
22#include <stdio.h>
23#include <signal.h>
24#include <limits.h>
25#include <ctype.h>
26#include <sys/wait.h>
27#include <unistd.h>
28
Carl Shapirod5c36b92011-04-15 18:38:06 -070029#include "Dalvik.h"
30#include "test/Test.h"
31#include "mterp/Mterp.h"
32#include "Hash.h"
33
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080034#define kMinHeapStartSize (1*1024*1024)
35#define kMinHeapSize (2*1024*1024)
36#define kMaxHeapSize (1*1024*1024*1024)
37
38/*
39 * Register VM-agnostic native methods for system classes.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080040 */
Carl Shapirod5c36b92011-04-15 18:38:06 -070041extern "C" int jniRegisterSystemMethods(JNIEnv* env);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080042
43/* fwd */
44static bool registerSystemNatives(JNIEnv* pEnv);
Carl Shapiro1e1433e2011-04-20 16:51:38 -070045static bool initJdwp();
46static bool initZygote();
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080047
48
49/* global state */
50struct DvmGlobals gDvm;
51
Ben Chengba4fc8b2009-06-01 13:00:29 -070052/* JIT-specific global state */
53#if defined(WITH_JIT)
54struct DvmJitGlobals gDvmJit;
Ben Cheng978738d2010-05-13 13:45:57 -070055
56#if defined(WITH_JIT_TUNING)
57/*
58 * Track the number of hits in the inline cache for predicted chaining.
59 * Use an ugly global variable here since it is accessed in assembly code.
60 */
61int gDvmICHitCount;
62#endif
63
Ben Chengba4fc8b2009-06-01 13:00:29 -070064#endif
65
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080066/*
67 * Show usage.
68 *
69 * We follow the tradition of unhyphenated compound words.
70 */
Carl Shapiroe5f172f2011-01-13 17:25:19 -080071static void usage(const char* progName)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080072{
73 dvmFprintf(stderr, "%s: [options] class [argument ...]\n", progName);
74 dvmFprintf(stderr, "%s: [options] -jar file.jar [argument ...]\n",progName);
75 dvmFprintf(stderr, "\n");
76 dvmFprintf(stderr, "The following standard options are recognized:\n");
77 dvmFprintf(stderr, " -classpath classpath\n");
78 dvmFprintf(stderr, " -Dproperty=value\n");
79 dvmFprintf(stderr, " -verbose:tag ('gc', 'jni', or 'class')\n");
80 dvmFprintf(stderr, " -ea[:<package name>... |:<class name>]\n");
81 dvmFprintf(stderr, " -da[:<package name>... |:<class name>]\n");
82 dvmFprintf(stderr, " (-enableassertions, -disableassertions)\n");
83 dvmFprintf(stderr, " -esa\n");
84 dvmFprintf(stderr, " -dsa\n");
85 dvmFprintf(stderr,
86 " (-enablesystemassertions, -disablesystemassertions)\n");
87 dvmFprintf(stderr, " -showversion\n");
88 dvmFprintf(stderr, " -help\n");
89 dvmFprintf(stderr, "\n");
90 dvmFprintf(stderr, "The following extended options are recognized:\n");
91 dvmFprintf(stderr, " -Xrunjdwp:<options>\n");
92 dvmFprintf(stderr, " -Xbootclasspath:bootclasspath\n");
93 dvmFprintf(stderr, " -Xcheck:tag (e.g. 'jni')\n");
94 dvmFprintf(stderr, " -XmsN (min heap, must be multiple of 1K, >= 1MB)\n");
95 dvmFprintf(stderr, " -XmxN (max heap, must be multiple of 1K, >= 2MB)\n");
96 dvmFprintf(stderr, " -XssN (stack size, >= %dKB, <= %dKB)\n",
97 kMinStackSize / 1024, kMaxStackSize / 1024);
98 dvmFprintf(stderr, " -Xverify:{none,remote,all}\n");
99 dvmFprintf(stderr, " -Xrs\n");
Ben Chengba4fc8b2009-06-01 13:00:29 -0700100#if defined(WITH_JIT)
101 dvmFprintf(stderr,
102 " -Xint (extended to accept ':portable', ':fast' and ':jit')\n");
103#else
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800104 dvmFprintf(stderr,
105 " -Xint (extended to accept ':portable' and ':fast')\n");
Ben Chengba4fc8b2009-06-01 13:00:29 -0700106#endif
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800107 dvmFprintf(stderr, "\n");
108 dvmFprintf(stderr, "These are unique to Dalvik:\n");
109 dvmFprintf(stderr, " -Xzygote\n");
Andy McFaddend18fcbc2011-02-24 16:53:55 -0800110 dvmFprintf(stderr, " -Xdexopt:{none,verified,all,full}\n");
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800111 dvmFprintf(stderr, " -Xnoquithandler\n");
112 dvmFprintf(stderr,
113 " -Xjnigreflimit:N (must be multiple of 100, >= 200)\n");
114 dvmFprintf(stderr, " -Xjniopts:{warnonly,forcecopy}\n");
Elliott Hughes8afa9df2010-07-07 14:47:25 -0700115 dvmFprintf(stderr, " -Xjnitrace:substring (eg NativeClass or nativeMethod)\n");
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800116 dvmFprintf(stderr, " -Xdeadlockpredict:{off,warn,err,abort}\n");
117 dvmFprintf(stderr, " -Xstacktracefile:<filename>\n");
The Android Open Source Project99409882009-03-18 22:20:24 -0700118 dvmFprintf(stderr, " -Xgc:[no]precise\n");
Barry Hayes962adba2010-03-17 12:12:39 -0700119 dvmFprintf(stderr, " -Xgc:[no]preverify\n");
120 dvmFprintf(stderr, " -Xgc:[no]postverify\n");
Carl Shapiroec805ea2010-06-28 16:28:26 -0700121 dvmFprintf(stderr, " -Xgc:[no]concurrent\n");
Barry Hayes6e5cf602010-06-22 12:32:59 -0700122 dvmFprintf(stderr, " -Xgc:[no]verifycardtable\n");
Carl Shapiro7007e042011-01-19 15:39:41 -0800123 dvmFprintf(stderr, " -XX:+DisableExplicitGC\n");
Andy McFadden701d2722010-12-01 16:18:19 -0800124 dvmFprintf(stderr, " -X[no]genregmap\n");
Andy McFadden3f64a022010-11-12 16:55:21 -0800125 dvmFprintf(stderr, " -Xverifyopt:[no]checkmon\n");
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800126 dvmFprintf(stderr, " -Xcheckdexsum\n");
Ben Chengba4fc8b2009-06-01 13:00:29 -0700127#if defined(WITH_JIT)
128 dvmFprintf(stderr, " -Xincludeselectedop\n");
129 dvmFprintf(stderr, " -Xjitop:hexopvalue[-endvalue]"
130 "[,hexopvalue[-endvalue]]*\n");
131 dvmFprintf(stderr, " -Xincludeselectedmethod\n");
Bill Buzbeed7269912009-11-10 14:31:32 -0800132 dvmFprintf(stderr, " -Xjitthreshold:decimalvalue\n");
133 dvmFprintf(stderr, " -Xjitblocking\n");
Elliott Hughesa8e7dc82010-01-07 15:42:39 -0800134 dvmFprintf(stderr, " -Xjitmethod:signature[,signature]* "
Ben Chengba4fc8b2009-06-01 13:00:29 -0700135 "(eg Ljava/lang/String\\;replace)\n");
Ben Cheng33672452010-01-12 14:59:30 -0800136 dvmFprintf(stderr, " -Xjitcheckcg\n");
Ben Chengba4fc8b2009-06-01 13:00:29 -0700137 dvmFprintf(stderr, " -Xjitverbose\n");
Bill Buzbee6e963e12009-06-17 16:56:19 -0700138 dvmFprintf(stderr, " -Xjitprofile\n");
Ben Chengdcf3e5d2009-09-11 13:42:05 -0700139 dvmFprintf(stderr, " -Xjitdisableopt\n");
Ben Cheng7ab74e12011-02-03 14:02:06 -0800140 dvmFprintf(stderr, " -Xjitsuspendpoll\n");
Ben Chengba4fc8b2009-06-01 13:00:29 -0700141#endif
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800142 dvmFprintf(stderr, "\n");
143 dvmFprintf(stderr, "Configured with:"
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800144 " debugger"
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800145 " profiler"
Andy McFadden3f64a022010-11-12 16:55:21 -0800146 " hprof"
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800147#ifdef WITH_TRACKREF_CHECKS
148 " trackref_checks"
149#endif
150#ifdef WITH_INSTR_CHECKS
151 " instr_checks"
152#endif
153#ifdef WITH_EXTRA_OBJECT_VALIDATION
154 " extra_object_validation"
155#endif
The Android Open Source Project99409882009-03-18 22:20:24 -0700156#ifdef WITH_EXTRA_GC_CHECKS
157 " extra_gc_checks"
158#endif
Andy McFaddena0b525d2010-08-04 12:47:21 -0700159#if !defined(NDEBUG) && defined(WITH_DALVIK_ASSERT)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800160 " dalvik_assert"
161#endif
162#ifdef WITH_JNI_STACK_CHECK
163 " jni_stack_check"
164#endif
165#ifdef EASY_GDB
166 " easy_gdb"
167#endif
168#ifdef CHECK_MUTEX
169 " check_mutex"
170#endif
171#ifdef PROFILE_FIELD_ACCESS
172 " profile_field_access"
173#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -0700174#if defined(WITH_JIT)
Ben Chengab961da2010-09-23 01:23:14 -0700175 " jit(" ARCH_VARIANT ")"
Jeff Hao97319a82009-08-12 16:57:15 -0700176#endif
177#if defined(WITH_SELF_VERIFICATION)
178 " self_verification"
Ben Chengba4fc8b2009-06-01 13:00:29 -0700179#endif
Andy McFadden6a877082010-05-19 22:36:33 -0700180#if ANDROID_SMP != 0
181 " smp"
182#endif
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800183 );
184#ifdef DVM_SHOW_EXCEPTION
185 dvmFprintf(stderr, " show_exception=%d", DVM_SHOW_EXCEPTION);
186#endif
187 dvmFprintf(stderr, "\n\n");
188}
189
190/*
191 * Show helpful information on JDWP options.
192 */
Carl Shapiro1e1433e2011-04-20 16:51:38 -0700193static void showJdwpHelp()
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800194{
195 dvmFprintf(stderr,
196 "Example: -Xrunjdwp:transport=dt_socket,address=8000,server=y\n");
197 dvmFprintf(stderr,
198 "Example: -Xrunjdwp:transport=dt_socket,address=localhost:6500,server=n\n");
199}
200
201/*
202 * Show version and copyright info.
203 */
Carl Shapiro1e1433e2011-04-20 16:51:38 -0700204static void showVersion()
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800205{
206 dvmFprintf(stdout, "DalvikVM version %d.%d.%d\n",
207 DALVIK_MAJOR_VERSION, DALVIK_MINOR_VERSION, DALVIK_BUG_VERSION);
Carl Shapirode750892010-06-08 16:37:12 -0700208 dvmFprintf(stdout,
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800209 "Copyright (C) 2007 The Android Open Source Project\n\n"
210 "This software is built from source code licensed under the "
211 "Apache License,\n"
212 "Version 2.0 (the \"License\"). You may obtain a copy of the "
213 "License at\n\n"
214 " http://www.apache.org/licenses/LICENSE-2.0\n\n"
215 "See the associated NOTICE file for this software for further "
216 "details.\n");
217}
218
219/*
220 * Parse a string of the form /[0-9]+[kKmMgG]?/, which is used to specify
221 * memory sizes. [kK] indicates kilobytes, [mM] megabytes, and
222 * [gG] gigabytes.
223 *
224 * "s" should point just past the "-Xm?" part of the string.
225 * "min" specifies the lowest acceptable value described by "s".
226 * "div" specifies a divisor, e.g. 1024 if the value must be a multiple
227 * of 1024.
228 *
229 * The spec says the -Xmx and -Xms options must be multiples of 1024. It
230 * doesn't say anything about -Xss.
231 *
232 * Returns 0 (a useless size) if "s" is malformed or specifies a low or
233 * non-evenly-divisible value.
234 */
Carl Shapiroe5f172f2011-01-13 17:25:19 -0800235static size_t parseMemOption(const char *s, size_t div)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800236{
237 /* strtoul accepts a leading [+-], which we don't want,
238 * so make sure our string starts with a decimal digit.
239 */
240 if (isdigit(*s)) {
241 const char *s2;
Carl Shapiroe5f172f2011-01-13 17:25:19 -0800242 size_t val;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800243
Carl Shapiroe5f172f2011-01-13 17:25:19 -0800244 val = strtoul(s, (char **)&s2, 10);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800245 if (s2 != s) {
246 /* s2 should be pointing just after the number.
247 * If this is the end of the string, the user
248 * has specified a number of bytes. Otherwise,
249 * there should be exactly one more character
250 * that specifies a multiplier.
251 */
252 if (*s2 != '\0') {
253 char c;
254
255 /* The remainder of the string is either a single multiplier
256 * character, or nothing to indicate that the value is in
257 * bytes.
258 */
259 c = *s2++;
260 if (*s2 == '\0') {
Carl Shapiroe5f172f2011-01-13 17:25:19 -0800261 size_t mul;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800262
263 if (c == '\0') {
264 mul = 1;
265 } else if (c == 'k' || c == 'K') {
266 mul = 1024;
267 } else if (c == 'm' || c == 'M') {
268 mul = 1024 * 1024;
269 } else if (c == 'g' || c == 'G') {
270 mul = 1024 * 1024 * 1024;
271 } else {
272 /* Unknown multiplier character.
273 */
274 return 0;
275 }
276
Carl Shapiroe5f172f2011-01-13 17:25:19 -0800277 if (val <= SIZE_MAX / mul) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800278 val *= mul;
279 } else {
280 /* Clamp to a multiple of 1024.
281 */
Carl Shapiroe5f172f2011-01-13 17:25:19 -0800282 val = SIZE_MAX & ~(1024-1);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800283 }
284 } else {
285 /* There's more than one character after the
286 * numeric part.
287 */
288 return 0;
289 }
290 }
291
292 /* The man page says that a -Xm value must be
293 * a multiple of 1024.
294 */
295 if (val % div == 0) {
296 return val;
297 }
298 }
299 }
300
301 return 0;
302}
303
304/*
305 * Handle one of the JDWP name/value pairs.
306 *
307 * JDWP options are:
308 * help: if specified, show help message and bail
309 * transport: may be dt_socket or dt_shmem
310 * address: for dt_socket, "host:port", or just "port" when listening
311 * server: if "y", wait for debugger to attach; if "n", attach to debugger
312 * timeout: how long to wait for debugger to connect / listen
313 *
314 * Useful with server=n (these aren't supported yet):
315 * onthrow=<exception-name>: connect to debugger when exception thrown
316 * onuncaught=y|n: connect to debugger when uncaught exception thrown
317 * launch=<command-line>: launch the debugger itself
318 *
319 * The "transport" option is required, as is "address" if server=n.
320 */
321static bool handleJdwpOption(const char* name, const char* value)
322{
323 if (strcmp(name, "transport") == 0) {
324 if (strcmp(value, "dt_socket") == 0) {
325 gDvm.jdwpTransport = kJdwpTransportSocket;
326 } else if (strcmp(value, "dt_android_adb") == 0) {
327 gDvm.jdwpTransport = kJdwpTransportAndroidAdb;
328 } else {
329 LOGE("JDWP transport '%s' not supported\n", value);
330 return false;
331 }
332 } else if (strcmp(name, "server") == 0) {
333 if (*value == 'n')
334 gDvm.jdwpServer = false;
335 else if (*value == 'y')
336 gDvm.jdwpServer = true;
337 else {
338 LOGE("JDWP option 'server' must be 'y' or 'n'\n");
339 return false;
340 }
341 } else if (strcmp(name, "suspend") == 0) {
342 if (*value == 'n')
343 gDvm.jdwpSuspend = false;
344 else if (*value == 'y')
345 gDvm.jdwpSuspend = true;
346 else {
347 LOGE("JDWP option 'suspend' must be 'y' or 'n'\n");
348 return false;
349 }
350 } else if (strcmp(name, "address") == 0) {
351 /* this is either <port> or <host>:<port> */
352 const char* colon = strchr(value, ':');
353 char* end;
354 long port;
355
356 if (colon != NULL) {
357 free(gDvm.jdwpHost);
358 gDvm.jdwpHost = (char*) malloc(colon - value +1);
359 strncpy(gDvm.jdwpHost, value, colon - value +1);
360 gDvm.jdwpHost[colon-value] = '\0';
361 value = colon + 1;
362 }
363 if (*value == '\0') {
364 LOGE("JDWP address missing port\n");
365 return false;
366 }
367 port = strtol(value, &end, 10);
368 if (*end != '\0') {
369 LOGE("JDWP address has junk in port field '%s'\n", value);
370 return false;
371 }
372 gDvm.jdwpPort = port;
373 } else if (strcmp(name, "launch") == 0 ||
374 strcmp(name, "onthrow") == 0 ||
375 strcmp(name, "oncaught") == 0 ||
376 strcmp(name, "timeout") == 0)
377 {
378 /* valid but unsupported */
379 LOGI("Ignoring JDWP option '%s'='%s'\n", name, value);
380 } else {
381 LOGI("Ignoring unrecognized JDWP option '%s'='%s'\n", name, value);
382 }
383
384 return true;
385}
386
387/*
388 * Parse the latter half of a -Xrunjdwp/-agentlib:jdwp= string, e.g.:
389 * "transport=dt_socket,address=8000,server=y,suspend=n"
390 */
391static bool parseJdwpOptions(const char* str)
392{
393 char* mangle = strdup(str);
394 char* name = mangle;
395 bool result = false;
396
397 /*
398 * Process all of the name=value pairs.
399 */
400 while (true) {
401 char* value;
402 char* comma;
403
404 value = strchr(name, '=');
405 if (value == NULL) {
406 LOGE("JDWP opts: garbage at '%s'\n", name);
407 goto bail;
408 }
409
410 comma = strchr(name, ','); // use name, not value, for safety
411 if (comma != NULL) {
412 if (comma < value) {
413 LOGE("JDWP opts: found comma before '=' in '%s'\n", mangle);
414 goto bail;
415 }
416 *comma = '\0';
417 }
418
419 *value++ = '\0'; // stomp the '='
420
421 if (!handleJdwpOption(name, value))
422 goto bail;
423
424 if (comma == NULL) {
425 /* out of options */
426 break;
427 }
428 name = comma+1;
429 }
430
431 /*
432 * Make sure the combination of arguments makes sense.
433 */
434 if (gDvm.jdwpTransport == kJdwpTransportUnknown) {
435 LOGE("JDWP opts: must specify transport\n");
436 goto bail;
437 }
438 if (!gDvm.jdwpServer && (gDvm.jdwpHost == NULL || gDvm.jdwpPort == 0)) {
439 LOGE("JDWP opts: when server=n, must specify host and port\n");
440 goto bail;
441 }
442 // transport mandatory
443 // outbound server address
444
445 gDvm.jdwpConfigured = true;
446 result = true;
447
448bail:
449 free(mangle);
450 return result;
451}
452
453/*
454 * Handle one of the four kinds of assertion arguments.
455 *
456 * "pkgOrClass" is the last part of an enable/disable line. For a package
457 * the arg looks like "-ea:com.google.fubar...", for a class it looks
458 * like "-ea:com.google.fubar.Wahoo". The string we get starts at the ':'.
459 *
460 * For system assertions (-esa/-dsa), "pkgOrClass" is NULL.
461 *
462 * Multiple instances of these arguments can be specified, e.g. you can
463 * enable assertions for a package and then disable them for one class in
464 * the package.
465 */
466static bool enableAssertions(const char* pkgOrClass, bool enable)
467{
468 AssertionControl* pCtrl = &gDvm.assertionCtrl[gDvm.assertionCtrlCount++];
469 pCtrl->enable = enable;
470
471 if (pkgOrClass == NULL) {
472 /* enable or disable for all system classes */
473 pCtrl->isPackage = false;
474 pCtrl->pkgOrClass = NULL;
475 pCtrl->pkgOrClassLen = 0;
476 } else {
477 if (*pkgOrClass == '\0') {
478 /* global enable/disable for all but system */
479 pCtrl->isPackage = false;
480 pCtrl->pkgOrClass = strdup("");
481 pCtrl->pkgOrClassLen = 0;
482 } else {
483 pCtrl->pkgOrClass = dvmDotToSlash(pkgOrClass+1); // skip ':'
484 if (pCtrl->pkgOrClass == NULL) {
485 /* can happen if class name includes an illegal '/' */
486 LOGW("Unable to process assertion arg '%s'\n", pkgOrClass);
487 return false;
488 }
489
490 int len = strlen(pCtrl->pkgOrClass);
491 if (len >= 3 && strcmp(pCtrl->pkgOrClass + len-3, "///") == 0) {
492 /* mark as package, truncate two of the three slashes */
493 pCtrl->isPackage = true;
494 *(pCtrl->pkgOrClass + len-2) = '\0';
495 pCtrl->pkgOrClassLen = len - 2;
496 } else {
497 /* just a class */
498 pCtrl->isPackage = false;
499 pCtrl->pkgOrClassLen = len;
500 }
501 }
502 }
503
504 return true;
505}
506
507/*
508 * Turn assertions on when requested to do so by the Zygote.
509 *
510 * This is a bit sketchy. We can't (easily) go back and fiddle with all
511 * of the classes that have already been initialized, so this only
512 * affects classes that have yet to be loaded. If some or all assertions
513 * have been enabled through some other means, we don't want to mess with
514 * it here, so we do nothing. Finally, we assume that there's room in
515 * "assertionCtrl" to hold at least one entry; this is guaranteed by the
516 * allocator.
517 *
518 * This must only be called from the main thread during zygote init.
519 */
Carl Shapiro1e1433e2011-04-20 16:51:38 -0700520void dvmLateEnableAssertions()
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800521{
522 if (gDvm.assertionCtrl == NULL) {
523 LOGD("Not late-enabling assertions: no assertionCtrl array\n");
524 return;
525 } else if (gDvm.assertionCtrlCount != 0) {
526 LOGD("Not late-enabling assertions: some asserts already configured\n");
527 return;
528 }
529 LOGD("Late-enabling assertions\n");
530
531 /* global enable for all but system */
532 AssertionControl* pCtrl = gDvm.assertionCtrl;
533 pCtrl->pkgOrClass = strdup("");
534 pCtrl->pkgOrClassLen = 0;
535 pCtrl->isPackage = false;
536 pCtrl->enable = true;
537 gDvm.assertionCtrlCount = 1;
538}
539
540
541/*
542 * Release memory associated with the AssertionCtrl array.
543 */
Carl Shapiro1e1433e2011-04-20 16:51:38 -0700544static void freeAssertionCtrl()
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800545{
546 int i;
547
548 for (i = 0; i < gDvm.assertionCtrlCount; i++)
549 free(gDvm.assertionCtrl[i].pkgOrClass);
550 free(gDvm.assertionCtrl);
551}
552
Ben Chengba4fc8b2009-06-01 13:00:29 -0700553#if defined(WITH_JIT)
554/* Parse -Xjitop to selectively turn on/off certain opcodes for JIT */
555static void processXjitop(const char *opt)
556{
557 if (opt[7] == ':') {
558 const char *startPtr = &opt[8];
559 char *endPtr = NULL;
560
561 do {
562 long startValue, endValue;
563
564 startValue = strtol(startPtr, &endPtr, 16);
565 if (startPtr != endPtr) {
566 /* Just in case value is out of range */
567 startValue &= 0xff;
568
569 if (*endPtr == '-') {
570 endValue = strtol(endPtr+1, &endPtr, 16);
571 endValue &= 0xff;
572 } else {
573 endValue = startValue;
574 }
575
576 for (; startValue <= endValue; startValue++) {
577 LOGW("Dalvik opcode %x is selected for debugging",
578 (unsigned int) startValue);
579 /* Mark the corresponding bit to 1 */
580 gDvmJit.opList[startValue >> 3] |=
581 1 << (startValue & 0x7);
582 }
583
584 if (*endPtr == 0) {
585 break;
586 }
587
588 startPtr = endPtr + 1;
589
590 continue;
591 } else {
592 if (*endPtr != 0) {
593 dvmFprintf(stderr,
594 "Warning: Unrecognized opcode value substring "
595 "%s\n", endPtr);
596 }
597 break;
598 }
599 } while (1);
600 } else {
601 int i;
602 for (i = 0; i < 32; i++) {
603 gDvmJit.opList[i] = 0xff;
604 }
605 dvmFprintf(stderr, "Warning: select all opcodes\n");
606 }
607}
608
609/* Parse -Xjitmethod to selectively turn on/off certain methods for JIT */
610static void processXjitmethod(const char *opt)
611{
612 char *buf = strdup(&opt[12]);
613 char *start, *end;
614
615 gDvmJit.methodTable = dvmHashTableCreate(8, NULL);
616
617 start = buf;
Carl Shapirode750892010-06-08 16:37:12 -0700618 /*
Ben Chengba4fc8b2009-06-01 13:00:29 -0700619 * Break comma-separated method signatures and enter them into the hash
620 * table individually.
621 */
622 do {
623 int hashValue;
624
625 end = strchr(start, ',');
626 if (end) {
627 *end = 0;
628 }
629
630 hashValue = dvmComputeUtf8Hash(start);
631
632 dvmHashTableLookup(gDvmJit.methodTable, hashValue,
633 strdup(start),
634 (HashCompareFunc) strcmp, true);
635 if (end) {
636 start = end + 1;
637 } else {
638 break;
639 }
640 } while (1);
641 free(buf);
642}
643#endif
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800644
645/*
646 * Process an argument vector full of options. Unlike standard C programs,
647 * argv[0] does not contain the name of the program.
648 *
649 * If "ignoreUnrecognized" is set, we ignore options starting with "-X" or "_"
650 * that we don't recognize. Otherwise, we return with an error as soon as
651 * we see anything we can't identify.
652 *
653 * Returns 0 on success, -1 on failure, and 1 for the special case of
654 * "-version" where we want to stop without showing an error message.
655 */
Carl Shapiroe5f172f2011-01-13 17:25:19 -0800656static int processOptions(int argc, const char* const argv[],
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800657 bool ignoreUnrecognized)
658{
659 int i;
660
661 LOGV("VM options (%d):\n", argc);
662 for (i = 0; i < argc; i++)
663 LOGV(" %d: '%s'\n", i, argv[i]);
664
665 /*
666 * Over-allocate AssertionControl array for convenience. If allocated,
667 * the array must be able to hold at least one entry, so that the
668 * zygote-time activation can do its business.
669 */
670 assert(gDvm.assertionCtrl == NULL);
671 if (argc > 0) {
672 gDvm.assertionCtrl =
673 (AssertionControl*) malloc(sizeof(AssertionControl) * argc);
674 if (gDvm.assertionCtrl == NULL)
675 return -1;
676 assert(gDvm.assertionCtrlCount == 0);
677 }
678
679 for (i = 0; i < argc; i++) {
680 if (strcmp(argv[i], "-help") == 0) {
681 /* show usage and stop */
682 return -1;
683
684 } else if (strcmp(argv[i], "-version") == 0) {
685 /* show version and stop */
686 showVersion();
687 return 1;
688 } else if (strcmp(argv[i], "-showversion") == 0) {
689 /* show version and continue */
690 showVersion();
691
692 } else if (strcmp(argv[i], "-classpath") == 0 ||
693 strcmp(argv[i], "-cp") == 0)
694 {
695 /* set classpath */
696 if (i == argc-1) {
697 dvmFprintf(stderr, "Missing classpath path list\n");
698 return -1;
699 }
700 free(gDvm.classPathStr); /* in case we have compiled-in default */
701 gDvm.classPathStr = strdup(argv[++i]);
702
703 } else if (strncmp(argv[i], "-Xbootclasspath:",
704 sizeof("-Xbootclasspath:")-1) == 0)
705 {
706 /* set bootclasspath */
707 const char* path = argv[i] + sizeof("-Xbootclasspath:")-1;
708
709 if (*path == '\0') {
710 dvmFprintf(stderr, "Missing bootclasspath path list\n");
711 return -1;
712 }
713 free(gDvm.bootClassPathStr);
714 gDvm.bootClassPathStr = strdup(path);
715
Norris, Lee60cc9932010-09-16 14:06:26 +0800716 } else if (strncmp(argv[i], "-Xbootclasspath/a:",
717 sizeof("-Xbootclasspath/a:")-1) == 0) {
718 const char* appPath = argv[i] + sizeof("-Xbootclasspath/a:")-1;
719
720 if (*(appPath) == '\0') {
721 dvmFprintf(stderr, "Missing appending bootclasspath path list\n");
722 return -1;
723 }
724 char* allPath;
725
726 if (asprintf(&allPath, "%s:%s", gDvm.bootClassPathStr, appPath) < 0) {
727 dvmFprintf(stderr, "Can't append to bootclasspath path list\n");
728 return -1;
729 }
730 free(gDvm.bootClassPathStr);
731 gDvm.bootClassPathStr = allPath;
732
733 } else if (strncmp(argv[i], "-Xbootclasspath/p:",
734 sizeof("-Xbootclasspath/p:")-1) == 0) {
735 const char* prePath = argv[i] + sizeof("-Xbootclasspath/p:")-1;
736
737 if (*(prePath) == '\0') {
738 dvmFprintf(stderr, "Missing prepending bootclasspath path list\n");
739 return -1;
740 }
741 char* allPath;
742
743 if (asprintf(&allPath, "%s:%s", prePath, gDvm.bootClassPathStr) < 0) {
744 dvmFprintf(stderr, "Can't prepend to bootclasspath path list\n");
745 return -1;
746 }
747 free(gDvm.bootClassPathStr);
748 gDvm.bootClassPathStr = allPath;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800749
750 } else if (strncmp(argv[i], "-D", 2) == 0) {
Elliott Hughes49dc0602011-02-10 12:03:34 -0800751 /* Properties are handled in managed code. We just check syntax. */
752 if (strchr(argv[i], '=') == NULL) {
753 dvmFprintf(stderr, "Bad system property setting: \"%s\"\n",
754 argv[i]);
755 return -1;
756 }
757 if (arrayAdd(gDvm.properties, strdup(argv[i] + 2)) == -1) {
758 dvmFprintf(stderr, "Can't set system property: \"%s\"\n",
759 argv[i]);
760 return -1;
761 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800762
763 } else if (strcmp(argv[i], "-jar") == 0) {
764 // TODO: handle this; name of jar should be in argv[i+1]
765 dvmFprintf(stderr, "-jar not yet handled\n");
766 assert(false);
767
768 } else if (strncmp(argv[i], "-Xms", 4) == 0) {
Carl Shapiroe5f172f2011-01-13 17:25:19 -0800769 size_t val = parseMemOption(argv[i]+4, 1024);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800770 if (val != 0) {
771 if (val >= kMinHeapStartSize && val <= kMaxHeapSize) {
Carl Shapirodf9f08b2011-01-18 17:59:30 -0800772 gDvm.heapStartingSize = val;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800773 } else {
774 dvmFprintf(stderr,
775 "Invalid -Xms '%s', range is %dKB to %dKB\n",
776 argv[i], kMinHeapStartSize/1024, kMaxHeapSize/1024);
777 return -1;
778 }
779 } else {
780 dvmFprintf(stderr, "Invalid -Xms option '%s'\n", argv[i]);
781 return -1;
782 }
783 } else if (strncmp(argv[i], "-Xmx", 4) == 0) {
Carl Shapiroe5f172f2011-01-13 17:25:19 -0800784 size_t val = parseMemOption(argv[i]+4, 1024);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800785 if (val != 0) {
786 if (val >= kMinHeapSize && val <= kMaxHeapSize) {
Carl Shapirodf9f08b2011-01-18 17:59:30 -0800787 gDvm.heapMaximumSize = val;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800788 } else {
789 dvmFprintf(stderr,
790 "Invalid -Xmx '%s', range is %dKB to %dKB\n",
791 argv[i], kMinHeapSize/1024, kMaxHeapSize/1024);
792 return -1;
793 }
794 } else {
795 dvmFprintf(stderr, "Invalid -Xmx option '%s'\n", argv[i]);
796 return -1;
797 }
Carl Shapirodf9f08b2011-01-18 17:59:30 -0800798 } else if (strncmp(argv[i], "-XX:HeapGrowthLimit=", 20) == 0) {
799 size_t val = parseMemOption(argv[i] + 20, 1024);
800 if (val != 0) {
801 gDvm.heapGrowthLimit = val;
802 } else {
803 dvmFprintf(stderr, "Invalid -XX:HeapGrowthLimit option '%s'\n", argv[i]);
804 return -1;
805 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800806 } else if (strncmp(argv[i], "-Xss", 4) == 0) {
Carl Shapiroe5f172f2011-01-13 17:25:19 -0800807 size_t val = parseMemOption(argv[i]+4, 1);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800808 if (val != 0) {
809 if (val >= kMinStackSize && val <= kMaxStackSize) {
810 gDvm.stackSize = val;
811 } else {
812 dvmFprintf(stderr, "Invalid -Xss '%s', range is %d to %d\n",
813 argv[i], kMinStackSize, kMaxStackSize);
814 return -1;
815 }
816 } else {
817 dvmFprintf(stderr, "Invalid -Xss option '%s'\n", argv[i]);
818 return -1;
819 }
820
Carl Shapiro821fd062011-01-19 12:56:14 -0800821 } else if (strncmp(argv[i], "-XX:+DisableExplicitGC", 22) == 0) {
822 gDvm.disableExplicitGc = true;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800823 } else if (strcmp(argv[i], "-verbose") == 0 ||
824 strcmp(argv[i], "-verbose:class") == 0)
825 {
826 // JNI spec says "-verbose:gc,class" is valid, but cmd line
827 // doesn't work that way; may want to support.
828 gDvm.verboseClass = true;
829 } else if (strcmp(argv[i], "-verbose:jni") == 0) {
830 gDvm.verboseJni = true;
831 } else if (strcmp(argv[i], "-verbose:gc") == 0) {
832 gDvm.verboseGc = true;
Andy McFadden43eb5012010-02-01 16:56:53 -0800833 } else if (strcmp(argv[i], "-verbose:shutdown") == 0) {
834 gDvm.verboseShutdown = true;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800835
836 } else if (strncmp(argv[i], "-enableassertions", 17) == 0) {
837 enableAssertions(argv[i] + 17, true);
838 } else if (strncmp(argv[i], "-ea", 3) == 0) {
839 enableAssertions(argv[i] + 3, true);
840 } else if (strncmp(argv[i], "-disableassertions", 18) == 0) {
841 enableAssertions(argv[i] + 18, false);
842 } else if (strncmp(argv[i], "-da", 3) == 0) {
843 enableAssertions(argv[i] + 3, false);
844 } else if (strcmp(argv[i], "-enablesystemassertions") == 0 ||
845 strcmp(argv[i], "-esa") == 0)
846 {
847 enableAssertions(NULL, true);
848 } else if (strcmp(argv[i], "-disablesystemassertions") == 0 ||
849 strcmp(argv[i], "-dsa") == 0)
850 {
851 enableAssertions(NULL, false);
852
853 } else if (strncmp(argv[i], "-Xcheck:jni", 11) == 0) {
854 /* nothing to do now -- was handled during JNI init */
855
856 } else if (strcmp(argv[i], "-Xdebug") == 0) {
857 /* accept but ignore */
858
859 } else if (strncmp(argv[i], "-Xrunjdwp:", 10) == 0 ||
860 strncmp(argv[i], "-agentlib:jdwp=", 15) == 0)
861 {
862 const char* tail;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800863
864 if (argv[i][1] == 'X')
865 tail = argv[i] + 10;
866 else
867 tail = argv[i] + 15;
868
869 if (strncmp(tail, "help", 4) == 0 || !parseJdwpOptions(tail)) {
870 showJdwpHelp();
871 return 1;
872 }
873 } else if (strcmp(argv[i], "-Xrs") == 0) {
874 gDvm.reduceSignals = true;
875 } else if (strcmp(argv[i], "-Xnoquithandler") == 0) {
876 /* disables SIGQUIT handler thread while still blocking SIGQUIT */
877 /* (useful if we don't want thread but system still signals us) */
878 gDvm.noQuitHandler = true;
879 } else if (strcmp(argv[i], "-Xzygote") == 0) {
880 gDvm.zygote = true;
Bill Buzbeefccb31d2010-02-04 16:09:55 -0800881#if defined(WITH_JIT)
882 gDvmJit.runningInAndroidFramework = true;
883#endif
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800884 } else if (strncmp(argv[i], "-Xdexopt:", 9) == 0) {
885 if (strcmp(argv[i] + 9, "none") == 0)
886 gDvm.dexOptMode = OPTIMIZE_MODE_NONE;
887 else if (strcmp(argv[i] + 9, "verified") == 0)
888 gDvm.dexOptMode = OPTIMIZE_MODE_VERIFIED;
889 else if (strcmp(argv[i] + 9, "all") == 0)
890 gDvm.dexOptMode = OPTIMIZE_MODE_ALL;
Andy McFaddend18fcbc2011-02-24 16:53:55 -0800891 else if (strcmp(argv[i] + 9, "full") == 0)
892 gDvm.dexOptMode = OPTIMIZE_MODE_FULL;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800893 else {
894 dvmFprintf(stderr, "Unrecognized dexopt option '%s'\n",argv[i]);
895 return -1;
896 }
897 } else if (strncmp(argv[i], "-Xverify:", 9) == 0) {
898 if (strcmp(argv[i] + 9, "none") == 0)
899 gDvm.classVerifyMode = VERIFY_MODE_NONE;
900 else if (strcmp(argv[i] + 9, "remote") == 0)
901 gDvm.classVerifyMode = VERIFY_MODE_REMOTE;
902 else if (strcmp(argv[i] + 9, "all") == 0)
903 gDvm.classVerifyMode = VERIFY_MODE_ALL;
904 else {
905 dvmFprintf(stderr, "Unrecognized verify option '%s'\n",argv[i]);
906 return -1;
907 }
908 } else if (strncmp(argv[i], "-Xjnigreflimit:", 15) == 0) {
909 int lim = atoi(argv[i] + 15);
910 if (lim < 200 || (lim % 100) != 0) {
911 dvmFprintf(stderr, "Bad value for -Xjnigreflimit: '%s'\n",
912 argv[i]+15);
913 return -1;
914 }
915 gDvm.jniGrefLimit = lim;
Elliott Hughes8afa9df2010-07-07 14:47:25 -0700916 } else if (strncmp(argv[i], "-Xjnitrace:", 11) == 0) {
917 gDvm.jniTrace = strdup(argv[i] + 11);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800918 } else if (strcmp(argv[i], "-Xlog-stdio") == 0) {
919 gDvm.logStdio = true;
920
921 } else if (strncmp(argv[i], "-Xint", 5) == 0) {
922 if (argv[i][5] == ':') {
923 if (strcmp(argv[i] + 6, "portable") == 0)
924 gDvm.executionMode = kExecutionModeInterpPortable;
925 else if (strcmp(argv[i] + 6, "fast") == 0)
926 gDvm.executionMode = kExecutionModeInterpFast;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700927#ifdef WITH_JIT
928 else if (strcmp(argv[i] + 6, "jit") == 0)
929 gDvm.executionMode = kExecutionModeJit;
930#endif
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800931 else {
932 dvmFprintf(stderr,
933 "Warning: Unrecognized interpreter mode %s\n",argv[i]);
934 /* keep going */
935 }
936 } else {
Andy McFadden5beebd02010-04-20 13:17:52 -0700937 /* disable JIT if it was enabled by default */
938 gDvm.executionMode = kExecutionModeInterpFast;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800939 }
940
Carl Shapirof0c514c2010-04-09 15:03:33 -0700941 } else if (strncmp(argv[i], "-Xlockprofthreshold:", 20) == 0) {
942 gDvm.lockProfThreshold = atoi(argv[i] + 20);
Carl Shapirof0c514c2010-04-09 15:03:33 -0700943
Ben Chengba4fc8b2009-06-01 13:00:29 -0700944#ifdef WITH_JIT
945 } else if (strncmp(argv[i], "-Xjitop", 7) == 0) {
946 processXjitop(argv[i]);
947 } else if (strncmp(argv[i], "-Xjitmethod", 11) == 0) {
948 processXjitmethod(argv[i]);
Bill Buzbeed7269912009-11-10 14:31:32 -0800949 } else if (strncmp(argv[i], "-Xjitblocking", 13) == 0) {
Ben Chengba4fc8b2009-06-01 13:00:29 -0700950 gDvmJit.blockingMode = true;
Bill Buzbeed7269912009-11-10 14:31:32 -0800951 } else if (strncmp(argv[i], "-Xjitthreshold:", 15) == 0) {
952 gDvmJit.threshold = atoi(argv[i] + 15);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700953 } else if (strncmp(argv[i], "-Xincludeselectedop", 19) == 0) {
954 gDvmJit.includeSelectedOp = true;
955 } else if (strncmp(argv[i], "-Xincludeselectedmethod", 23) == 0) {
956 gDvmJit.includeSelectedMethod = true;
Ben Cheng33672452010-01-12 14:59:30 -0800957 } else if (strncmp(argv[i], "-Xjitcheckcg", 12) == 0) {
958 gDvmJit.checkCallGraph = true;
959 /* Need to enable blocking mode due to stack crawling */
960 gDvmJit.blockingMode = true;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700961 } else if (strncmp(argv[i], "-Xjitverbose", 12) == 0) {
962 gDvmJit.printMe = true;
Bill Buzbee6e963e12009-06-17 16:56:19 -0700963 } else if (strncmp(argv[i], "-Xjitprofile", 12) == 0) {
buzbee2e152ba2010-12-15 16:32:35 -0800964 gDvmJit.profileMode = kTraceProfilingContinuous;
Ben Cheng502528b2010-04-01 13:26:54 -0700965 } else if (strncmp(argv[i], "-Xjitdisableopt", 15) == 0) {
966 /* Disable selected optimizations */
967 if (argv[i][15] == ':') {
968 sscanf(argv[i] + 16, "%x", &gDvmJit.disableOpt);
969 /* Disable all optimizations */
970 } else {
971 gDvmJit.disableOpt = -1;
972 }
Ben Cheng7ab74e12011-02-03 14:02:06 -0800973 } else if (strncmp(argv[i], "-Xjitsuspendpoll", 16) == 0) {
974 gDvmJit.genSuspendPoll = true;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700975#endif
976
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800977 } else if (strncmp(argv[i], "-Xstacktracefile:", 17) == 0) {
978 gDvm.stackTraceFile = strdup(argv[i]+17);
979
980 } else if (strcmp(argv[i], "-Xgenregmap") == 0) {
981 gDvm.generateRegisterMaps = true;
Andy McFadden701d2722010-12-01 16:18:19 -0800982 } else if (strcmp(argv[i], "-Xnogenregmap") == 0) {
983 gDvm.generateRegisterMaps = false;
The Android Open Source Project99409882009-03-18 22:20:24 -0700984
Andy McFadden3f64a022010-11-12 16:55:21 -0800985 } else if (strcmp(argv[i], "Xverifyopt:checkmon") == 0) {
986 gDvm.monitorVerification = true;
987 } else if (strcmp(argv[i], "Xverifyopt:nocheckmon") == 0) {
988 gDvm.monitorVerification = false;
989
The Android Open Source Project99409882009-03-18 22:20:24 -0700990 } else if (strncmp(argv[i], "-Xgc:", 5) == 0) {
991 if (strcmp(argv[i] + 5, "precise") == 0)
992 gDvm.preciseGc = true;
993 else if (strcmp(argv[i] + 5, "noprecise") == 0)
994 gDvm.preciseGc = false;
Barry Hayes962adba2010-03-17 12:12:39 -0700995 else if (strcmp(argv[i] + 5, "preverify") == 0)
996 gDvm.preVerify = true;
997 else if (strcmp(argv[i] + 5, "nopreverify") == 0)
998 gDvm.preVerify = false;
999 else if (strcmp(argv[i] + 5, "postverify") == 0)
1000 gDvm.postVerify = true;
1001 else if (strcmp(argv[i] + 5, "nopostverify") == 0)
1002 gDvm.postVerify = false;
Carl Shapiroec805ea2010-06-28 16:28:26 -07001003 else if (strcmp(argv[i] + 5, "concurrent") == 0)
1004 gDvm.concurrentMarkSweep = true;
1005 else if (strcmp(argv[i] + 5, "noconcurrent") == 0)
1006 gDvm.concurrentMarkSweep = false;
Barry Hayes6e5cf602010-06-22 12:32:59 -07001007 else if (strcmp(argv[i] + 5, "verifycardtable") == 0)
1008 gDvm.verifyCardTable = true;
1009 else if (strcmp(argv[i] + 5, "noverifycardtable") == 0)
1010 gDvm.verifyCardTable = false;
The Android Open Source Project99409882009-03-18 22:20:24 -07001011 else {
1012 dvmFprintf(stderr, "Bad value for -Xgc");
1013 return -1;
1014 }
Andy McFadden43eb5012010-02-01 16:56:53 -08001015 LOGV("Precise GC configured %s\n", gDvm.preciseGc ? "ON" : "OFF");
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001016
1017 } else if (strcmp(argv[i], "-Xcheckdexsum") == 0) {
1018 gDvm.verifyDexChecksum = true;
1019
Andy McFaddenea414342010-08-25 12:05:44 -07001020 } else if (strcmp(argv[i], "-Xprofile:wallclock") == 0) {
1021 gDvm.profilerWallClock = true;
1022
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001023 } else {
1024 if (!ignoreUnrecognized) {
1025 dvmFprintf(stderr, "Unrecognized option '%s'\n", argv[i]);
1026 return -1;
1027 }
1028 }
1029 }
1030
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001031 return 0;
1032}
1033
1034/*
1035 * Set defaults for fields altered or modified by arguments.
The Android Open Source Project99409882009-03-18 22:20:24 -07001036 *
1037 * Globals are initialized to 0 (a/k/a NULL or false).
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001038 */
1039static void setCommandLineDefaults()
1040{
1041 const char* envStr;
1042
1043 envStr = getenv("CLASSPATH");
1044 if (envStr != NULL)
1045 gDvm.classPathStr = strdup(envStr);
1046 else
1047 gDvm.classPathStr = strdup(".");
1048 envStr = getenv("BOOTCLASSPATH");
1049 if (envStr != NULL)
1050 gDvm.bootClassPathStr = strdup(envStr);
1051 else
1052 gDvm.bootClassPathStr = strdup(".");
1053
1054 /* Defaults overridden by -Xms and -Xmx.
1055 * TODO: base these on a system or application-specific default
1056 */
Carl Shapirodf9f08b2011-01-18 17:59:30 -08001057 gDvm.heapStartingSize = 2 * 1024 * 1024; // Spec says 16MB; too big for us.
1058 gDvm.heapMaximumSize = 16 * 1024 * 1024; // Spec says 75% physical mem
1059 gDvm.heapGrowthLimit = 0; // 0 means no growth limit
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001060 gDvm.stackSize = kDefaultStackSize;
1061
Carl Shapiro03b837b2010-07-12 14:04:42 -07001062 gDvm.concurrentMarkSweep = true;
1063
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001064 /* gDvm.jdwpSuspend = true; */
1065
1066 /* allowed unless zygote config doesn't allow it */
1067 gDvm.jdwpAllowed = true;
1068
1069 /* default verification and optimization modes */
1070 gDvm.classVerifyMode = VERIFY_MODE_ALL;
1071 gDvm.dexOptMode = OPTIMIZE_MODE_VERIFIED;
Andy McFadden3f64a022010-11-12 16:55:21 -08001072 gDvm.monitorVerification = false;
Andy McFadden701d2722010-12-01 16:18:19 -08001073 gDvm.generateRegisterMaps = true;
1074 gDvm.registerMapMode = kRegisterMapModeTypePrecise;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001075
1076 /*
1077 * Default execution mode.
1078 *
1079 * This should probably interact with the mterp code somehow, e.g. if
1080 * we know we're using the "desktop" build we should probably be
1081 * using "portable" rather than "fast".
1082 */
Ben Chengba4fc8b2009-06-01 13:00:29 -07001083#if defined(WITH_JIT)
1084 gDvm.executionMode = kExecutionModeJit;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001085#else
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001086 gDvm.executionMode = kExecutionModeInterpFast;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001087#endif
Andy McFaddenc58b9ef2010-09-09 12:54:43 -07001088
1089 /*
1090 * SMP support is a compile-time define, but we may want to have
1091 * dexopt target a differently-configured device.
1092 */
1093 gDvm.dexOptForSmp = (ANDROID_SMP != 0);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001094}
1095
1096
1097/*
1098 * Handle a SIGBUS, which frequently occurs because somebody replaced an
1099 * optimized DEX file out from under us.
1100 */
1101static void busCatcher(int signum, siginfo_t* info, void* context)
1102{
1103 void* addr = info->si_addr;
1104
1105 LOGE("Caught a SIGBUS (%d), addr=%p\n", signum, addr);
1106
1107 /*
1108 * If we return at this point the SIGBUS just keeps happening, so we
1109 * remove the signal handler and allow it to kill us. TODO: restore
1110 * the original, which points to a debuggerd stub; if we don't then
1111 * debuggerd won't be notified.
1112 */
1113 signal(SIGBUS, SIG_DFL);
1114}
1115
1116/*
1117 * Configure signals. We need to block SIGQUIT so that the signal only
1118 * reaches the dump-stack-trace thread.
1119 *
1120 * This can be disabled with the "-Xrs" flag.
1121 */
1122static void blockSignals()
1123{
1124 sigset_t mask;
1125 int cc;
1126
1127 sigemptyset(&mask);
1128 sigaddset(&mask, SIGQUIT);
1129 sigaddset(&mask, SIGUSR1); // used to initiate heap dump
Ben Chengba4fc8b2009-06-01 13:00:29 -07001130#if defined(WITH_JIT) && defined(WITH_JIT_TUNING)
1131 sigaddset(&mask, SIGUSR2); // used to investigate JIT internals
1132#endif
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001133 //sigaddset(&mask, SIGPIPE);
1134 cc = sigprocmask(SIG_BLOCK, &mask, NULL);
1135 assert(cc == 0);
1136
1137 if (false) {
1138 /* TODO: save the old sigaction in a global */
1139 struct sigaction sa;
1140 memset(&sa, 0, sizeof(sa));
1141 sa.sa_sigaction = busCatcher;
1142 sa.sa_flags = SA_SIGINFO;
1143 cc = sigaction(SIGBUS, &sa, NULL);
1144 assert(cc == 0);
1145 }
1146}
1147
1148/*
1149 * VM initialization. Pass in any options provided on the command line.
1150 * Do not pass in the class name or the options for the class.
1151 *
1152 * Returns 0 on success.
1153 */
1154int dvmStartup(int argc, const char* const argv[], bool ignoreUnrecognized,
1155 JNIEnv* pEnv)
1156{
1157 int i, cc;
1158
1159 assert(gDvm.initializing);
1160
1161 LOGV("VM init args (%d):\n", argc);
1162 for (i = 0; i < argc; i++)
1163 LOGV(" %d: '%s'\n", i, argv[i]);
1164
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001165 /* prep properties storage */
Elliott Hughes49dc0602011-02-10 12:03:34 -08001166 if (!dvmPropertiesStartup())
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001167 goto fail;
1168
Elliott Hughes49dc0602011-02-10 12:03:34 -08001169 setCommandLineDefaults();
1170
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001171 /*
1172 * Process the option flags (if any).
1173 */
Carl Shapiroe5f172f2011-01-13 17:25:19 -08001174 cc = processOptions(argc, argv, ignoreUnrecognized);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001175 if (cc != 0) {
1176 if (cc < 0) {
1177 dvmFprintf(stderr, "\n");
Carl Shapiroe5f172f2011-01-13 17:25:19 -08001178 usage("dalvikvm");
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001179 }
1180 goto fail;
1181 }
1182
The Android Open Source Project99409882009-03-18 22:20:24 -07001183#if WITH_EXTRA_GC_CHECKS > 1
1184 /* only "portable" interp has the extra goodies */
1185 if (gDvm.executionMode != kExecutionModeInterpPortable) {
1186 LOGI("Switching to 'portable' interpreter for GC checks\n");
1187 gDvm.executionMode = kExecutionModeInterpPortable;
1188 }
1189#endif
1190
San Mehat894dd462009-09-08 20:29:15 -07001191 /* Configure group scheduling capabilities */
1192 if (!access("/dev/cpuctl/tasks", F_OK)) {
1193 LOGV("Using kernel group scheduling");
1194 gDvm.kernelGroupScheduling = 1;
1195 } else {
1196 LOGV("Using kernel scheduler policies");
1197 }
1198
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001199 /* configure signal handling */
1200 if (!gDvm.reduceSignals)
1201 blockSignals();
1202
Andy McFadden96516932009-10-28 17:39:02 -07001203 /* verify system page size */
1204 if (sysconf(_SC_PAGESIZE) != SYSTEM_PAGE_SIZE) {
1205 LOGE("ERROR: expected page size %d, got %d\n",
1206 SYSTEM_PAGE_SIZE, (int) sysconf(_SC_PAGESIZE));
1207 goto fail;
1208 }
1209
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001210 /* mterp setup */
1211 LOGV("Using executionMode %d\n", gDvm.executionMode);
1212 dvmCheckAsmConstants();
1213
1214 /*
1215 * Initialize components.
1216 */
1217 if (!dvmAllocTrackerStartup())
1218 goto fail;
1219 if (!dvmGcStartup())
1220 goto fail;
1221 if (!dvmThreadStartup())
1222 goto fail;
1223 if (!dvmInlineNativeStartup())
1224 goto fail;
The Android Open Source Project99409882009-03-18 22:20:24 -07001225 if (!dvmRegisterMapStartup())
1226 goto fail;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001227 if (!dvmInstanceofStartup())
1228 goto fail;
1229 if (!dvmClassStartup())
1230 goto fail;
Dan Bornstein85213112011-03-01 16:16:12 -08001231
1232 /*
1233 * At this point, the system is guaranteed to be sufficiently
1234 * initialized that we can look up classes and class members. This
1235 * call populates the gDvm instance with all the class and member
1236 * references that the VM wants to use directly.
1237 */
Dan Bornstein4b5fa2e2011-03-02 15:08:54 -08001238 if (!dvmFindRequiredClassesAndMembers())
Dan Bornstein85213112011-03-01 16:16:12 -08001239 goto fail;
1240
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001241 if (!dvmStringInternStartup())
1242 goto fail;
1243 if (!dvmNativeStartup())
1244 goto fail;
1245 if (!dvmInternalNativeStartup())
1246 goto fail;
1247 if (!dvmJniStartup())
1248 goto fail;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001249 if (!dvmProfilingStartup())
1250 goto fail;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001251
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001252 /*
Andy McFadden65a54dc2011-01-27 17:01:54 -08001253 * Create a table of methods for which we will substitute an "inline"
1254 * version for performance.
1255 */
1256 if (!dvmCreateInlineSubsTable())
1257 goto fail;
1258
1259 /*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001260 * Miscellaneous class library validation.
1261 */
1262 if (!dvmValidateBoxClasses())
1263 goto fail;
1264
1265 /*
1266 * Do the last bits of Thread struct initialization we need to allow
1267 * JNI calls to work.
1268 */
1269 if (!dvmPrepMainForJni(pEnv))
1270 goto fail;
1271
1272 /*
Andy McFadden9ef5ca62010-10-05 17:02:54 -07001273 * Explicitly initialize java.lang.Class. This doesn't happen
1274 * automatically because it's allocated specially (it's an instance
1275 * of itself). Must happen before registration of system natives,
1276 * which make some calls that throw assertions if the classes they
1277 * operate on aren't initialized.
1278 */
1279 if (!dvmInitClass(gDvm.classJavaLangClass))
1280 goto fail;
1281
1282 /*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001283 * Register the system native methods, which are registered through JNI.
1284 */
1285 if (!registerSystemNatives(pEnv))
1286 goto fail;
1287
1288 /*
1289 * Do some "late" initialization for the memory allocator. This may
1290 * allocate storage and initialize classes.
1291 */
Andy McFadden7fc3ce82009-07-14 15:57:23 -07001292 if (!dvmCreateStockExceptions())
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001293 goto fail;
1294
1295 /*
1296 * At this point, the VM is in a pretty good state. Finish prep on
1297 * the main thread (specifically, create a java.lang.Thread object to go
1298 * along with our Thread struct). Note we will probably be executing
1299 * some interpreted class initializer code in here.
1300 */
1301 if (!dvmPrepMainThread())
1302 goto fail;
1303
Andy McFaddenafcd1eb2010-03-01 10:52:00 -08001304 /*
1305 * Make sure we haven't accumulated any tracked references. The main
1306 * thread should be starting with a clean slate.
1307 */
1308 if (dvmReferenceTableEntries(&dvmThreadSelf()->internalLocalRefTable) != 0)
1309 {
1310 LOGW("Warning: tracked references remain post-initialization\n");
1311 dvmDumpReferenceTable(&dvmThreadSelf()->internalLocalRefTable, "MAIN");
1312 }
1313
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001314 /* general debugging setup */
1315 if (!dvmDebuggerStartup())
1316 goto fail;
1317
Carl Shapiroce87bfe2011-03-30 19:35:34 -07001318 if (!dvmGcStartupClasses())
1319 goto fail;
1320
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001321 /*
1322 * Init for either zygote mode or non-zygote mode. The key difference
1323 * is that we don't start any additional threads in Zygote mode.
1324 */
1325 if (gDvm.zygote) {
Carl Shapiroe5f172f2011-01-13 17:25:19 -08001326 if (!initZygote())
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001327 goto fail;
1328 } else {
1329 if (!dvmInitAfterZygote())
1330 goto fail;
1331 }
1332
1333
1334#ifndef NDEBUG
Andy McFadden734155e2009-07-16 18:11:22 -07001335 if (!dvmTestHash())
Carl Shapirod5c36b92011-04-15 18:38:06 -07001336 LOGE("dvmTestHash FAILED\n");
Andy McFadden734155e2009-07-16 18:11:22 -07001337 if (false /*noisy!*/ && !dvmTestIndirectRefTable())
1338 LOGE("dvmTestIndirectRefTable FAILED\n");
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001339#endif
1340
Andy McFadden8cd640b2011-03-22 16:17:09 -07001341 if (dvmCheckException(dvmThreadSelf())) {
1342 LOGE("Exception pending at end of VM initialization\n");
1343 dvmLogExceptionStackTrace();
1344 goto fail;
1345 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001346
1347 return 0;
1348
1349fail:
1350 dvmShutdown();
1351 return 1;
1352}
1353
1354/*
1355 * Register java.* natives from our class libraries. We need to do
1356 * this after we're ready for JNI registration calls, but before we
1357 * do any class initialization.
1358 *
1359 * If we get this wrong, we will blow up in the ThreadGroup class init if
1360 * interpreted code makes any reference to System. It will likely do this
1361 * since it wants to do some java.io.File setup (e.g. for static in/out/err).
1362 *
1363 * We need to have gDvm.initializing raised here so that JNI FindClass
1364 * won't try to use the system/application class loader.
1365 */
1366static bool registerSystemNatives(JNIEnv* pEnv)
1367{
1368 Thread* self;
1369
1370 /* main thread is always first in list */
1371 self = gDvm.threadList;
1372
1373 /* must set this before allowing JNI-based method registration */
1374 self->status = THREAD_NATIVE;
1375
1376 if (jniRegisterSystemMethods(pEnv) < 0) {
Elliott Hughesfe700262010-09-14 17:42:07 -07001377 LOGE("jniRegisterSystemMethods failed");
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001378 return false;
1379 }
1380
1381 /* back to run mode */
1382 self->status = THREAD_RUNNING;
1383
1384 return true;
1385}
1386
1387
1388/*
1389 * Do zygote-mode-only initialization.
1390 */
Carl Shapiro1e1433e2011-04-20 16:51:38 -07001391static bool initZygote()
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001392{
1393 /* zygote goes into its own process group */
1394 setpgid(0,0);
1395
1396 return true;
1397}
1398
1399/*
1400 * Do non-zygote-mode initialization. This is done during VM init for
1401 * standard startup, or after a "zygote fork" when creating a new process.
1402 */
Carl Shapiro1e1433e2011-04-20 16:51:38 -07001403bool dvmInitAfterZygote()
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001404{
1405 u8 startHeap, startQuit, startJdwp;
1406 u8 endHeap, endQuit, endJdwp;
Carl Shapirode750892010-06-08 16:37:12 -07001407
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001408 startHeap = dvmGetRelativeTimeUsec();
1409
1410 /*
1411 * Post-zygote heap initialization, including starting
1412 * the HeapWorker thread.
1413 */
1414 if (!dvmGcStartupAfterZygote())
1415 return false;
1416
1417 endHeap = dvmGetRelativeTimeUsec();
1418 startQuit = dvmGetRelativeTimeUsec();
1419
1420 /* start signal catcher thread that dumps stacks on SIGQUIT */
1421 if (!gDvm.reduceSignals && !gDvm.noQuitHandler) {
1422 if (!dvmSignalCatcherStartup())
1423 return false;
1424 }
1425
1426 /* start stdout/stderr copier, if requested */
1427 if (gDvm.logStdio) {
1428 if (!dvmStdioConverterStartup())
1429 return false;
1430 }
1431
1432 endQuit = dvmGetRelativeTimeUsec();
1433 startJdwp = dvmGetRelativeTimeUsec();
1434
1435 /*
1436 * Start JDWP thread. If the command-line debugger flags specified
1437 * "suspend=y", this will pause the VM. We probably want this to
1438 * come last.
1439 */
Carl Shapiroe5f172f2011-01-13 17:25:19 -08001440 if (!initJdwp()) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001441 LOGD("JDWP init failed; continuing anyway\n");
1442 }
1443
1444 endJdwp = dvmGetRelativeTimeUsec();
1445
1446 LOGV("thread-start heap=%d quit=%d jdwp=%d total=%d usec\n",
1447 (int)(endHeap-startHeap), (int)(endQuit-startQuit),
1448 (int)(endJdwp-startJdwp), (int)(endJdwp-startHeap));
1449
Ben Chengba4fc8b2009-06-01 13:00:29 -07001450#ifdef WITH_JIT
Ben Cheng580e09e2009-10-09 11:55:30 -07001451 if (gDvm.executionMode == kExecutionModeJit) {
Bill Buzbee5e7bfdf2010-02-08 17:08:15 -08001452 if (!dvmCompilerStartup())
Ben Cheng580e09e2009-10-09 11:55:30 -07001453 return false;
1454 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07001455#endif
1456
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001457 return true;
1458}
1459
1460/*
1461 * Prepare for a connection to a JDWP-compliant debugger.
1462 *
1463 * Note this needs to happen fairly late in the startup process, because
1464 * we need to have all of the java.* native methods registered (which in
1465 * turn requires JNI to be fully prepped).
1466 *
1467 * There are several ways to initialize:
1468 * server=n
1469 * We immediately try to connect to host:port. Bail on failure. On
1470 * success, send VM_START (suspending the VM if "suspend=y").
1471 * server=y suspend=n
1472 * Passively listen for a debugger to connect. Return immediately.
1473 * server=y suspend=y
1474 * Wait until debugger connects. Send VM_START ASAP, suspending the
1475 * VM after the message is sent.
1476 *
1477 * This gets more complicated with a nonzero value for "timeout".
1478 */
Carl Shapiro1e1433e2011-04-20 16:51:38 -07001479static bool initJdwp()
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001480{
1481 assert(!gDvm.zygote);
1482
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001483 /*
1484 * Init JDWP if the debugger is enabled. This may connect out to a
1485 * debugger, passively listen for a debugger, or block waiting for a
1486 * debugger.
1487 */
1488 if (gDvm.jdwpAllowed && gDvm.jdwpConfigured) {
1489 JdwpStartupParams params;
1490
1491 if (gDvm.jdwpHost != NULL) {
1492 if (strlen(gDvm.jdwpHost) >= sizeof(params.host)-1) {
1493 LOGE("ERROR: hostname too long: '%s'\n", gDvm.jdwpHost);
1494 return false;
1495 }
1496 strcpy(params.host, gDvm.jdwpHost);
1497 } else {
1498 params.host[0] = '\0';
1499 }
1500 params.transport = gDvm.jdwpTransport;
1501 params.server = gDvm.jdwpServer;
1502 params.suspend = gDvm.jdwpSuspend;
1503 params.port = gDvm.jdwpPort;
1504
1505 gDvm.jdwpState = dvmJdwpStartup(&params);
1506 if (gDvm.jdwpState == NULL) {
1507 LOGW("WARNING: debugger thread failed to initialize\n");
1508 /* TODO: ignore? fail? need to mimic "expected" behavior */
1509 }
1510 }
1511
1512 /*
1513 * If a debugger has already attached, send the "welcome" message. This
1514 * may cause us to suspend all threads.
1515 */
1516 if (dvmJdwpIsActive(gDvm.jdwpState)) {
1517 //dvmChangeStatus(NULL, THREAD_RUNNING);
1518 if (!dvmJdwpPostVMStart(gDvm.jdwpState, gDvm.jdwpSuspend)) {
1519 LOGW("WARNING: failed to post 'start' message to debugger\n");
1520 /* keep going */
1521 }
1522 //dvmChangeStatus(NULL, THREAD_NATIVE);
1523 }
1524
1525 return true;
1526}
1527
1528/*
1529 * An alternative to JNI_CreateJavaVM/dvmStartup that does the first bit
1530 * of initialization and then returns with "initializing" still set. (Used
1531 * by DexOpt command-line utility.)
1532 *
Andy McFaddenef22d6f2010-10-22 12:41:33 -07001533 * Attempting to use JNI or internal natives will fail. It's best
1534 * if no bytecode gets executed, which means no <clinit>, which means
1535 * no exception-throwing. (In practice we need to initialize Class and
1536 * Object, and probably some exception classes.)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001537 *
1538 * Returns 0 on success.
1539 */
1540int dvmPrepForDexOpt(const char* bootClassPath, DexOptimizerMode dexOptMode,
1541 DexClassVerifyMode verifyMode, int dexoptFlags)
1542{
1543 gDvm.initializing = true;
1544 gDvm.optimizing = true;
1545
1546 /* configure signal handling */
1547 blockSignals();
1548
1549 /* set some defaults */
1550 setCommandLineDefaults();
1551 free(gDvm.bootClassPathStr);
1552 gDvm.bootClassPathStr = strdup(bootClassPath);
1553
1554 /* set opt/verify modes */
1555 gDvm.dexOptMode = dexOptMode;
1556 gDvm.classVerifyMode = verifyMode;
1557 gDvm.generateRegisterMaps = (dexoptFlags & DEXOPT_GEN_REGISTER_MAPS) != 0;
Andy McFaddenb91b37e2010-09-30 14:02:54 -07001558 if (dexoptFlags & DEXOPT_SMP) {
1559 assert((dexoptFlags & DEXOPT_UNIPROCESSOR) == 0);
1560 gDvm.dexOptForSmp = true;
1561 } else if (dexoptFlags & DEXOPT_UNIPROCESSOR) {
1562 gDvm.dexOptForSmp = false;
1563 } else {
1564 gDvm.dexOptForSmp = (ANDROID_SMP != 0);
1565 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001566
1567 /*
1568 * Initialize the heap, some basic thread control mutexes, and
1569 * get the bootclasspath prepped.
1570 *
1571 * We can't load any classes yet because we may not yet have a source
1572 * for things like java.lang.Object and java.lang.Class.
1573 */
1574 if (!dvmGcStartup())
1575 goto fail;
1576 if (!dvmThreadStartup())
1577 goto fail;
1578 if (!dvmInlineNativeStartup())
1579 goto fail;
The Android Open Source Project99409882009-03-18 22:20:24 -07001580 if (!dvmRegisterMapStartup())
1581 goto fail;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001582 if (!dvmInstanceofStartup())
1583 goto fail;
1584 if (!dvmClassStartup())
1585 goto fail;
1586
1587 /*
1588 * We leave gDvm.initializing set to "true" so that, if we're not
1589 * able to process the "core" classes, we don't go into a death-spin
1590 * trying to throw a "class not found" exception.
1591 */
1592
1593 return 0;
1594
1595fail:
1596 dvmShutdown();
1597 return 1;
1598}
1599
1600
1601/*
1602 * All threads have stopped. Finish the shutdown procedure.
1603 *
1604 * We can also be called if startup fails partway through, so be prepared
1605 * to deal with partially initialized data.
1606 *
1607 * Free any storage allocated in gGlobals.
1608 *
1609 * We can't dlclose() shared libs we've loaded, because it's possible a
1610 * thread not associated with the VM is running code in one.
1611 *
1612 * This is called from the JNI DestroyJavaVM function, which can be
1613 * called from any thread. (In practice, this will usually run in the
1614 * same thread that started the VM, a/k/a the main thread, but we don't
1615 * want to assume that.)
1616 */
Carl Shapiro1e1433e2011-04-20 16:51:38 -07001617void dvmShutdown()
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001618{
1619 LOGV("VM shutting down\n");
1620
1621 if (CALC_CACHE_STATS)
1622 dvmDumpAtomicCacheStats(gDvm.instanceofCache);
1623
1624 /*
1625 * Stop our internal threads.
1626 */
Carl Shapiroec805ea2010-06-28 16:28:26 -07001627 dvmGcThreadShutdown();
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001628
1629 if (gDvm.jdwpState != NULL)
1630 dvmJdwpShutdown(gDvm.jdwpState);
1631 free(gDvm.jdwpHost);
1632 gDvm.jdwpHost = NULL;
Elliott Hughes8afa9df2010-07-07 14:47:25 -07001633 free(gDvm.jniTrace);
1634 gDvm.jniTrace = NULL;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001635 free(gDvm.stackTraceFile);
1636 gDvm.stackTraceFile = NULL;
1637
1638 /* tell signal catcher to shut down if it was started */
1639 dvmSignalCatcherShutdown();
1640
1641 /* shut down stdout/stderr conversion */
1642 dvmStdioConverterShutdown();
1643
Ben Chengef00a852009-06-22 22:53:35 -07001644#ifdef WITH_JIT
Ben Cheng580e09e2009-10-09 11:55:30 -07001645 if (gDvm.executionMode == kExecutionModeJit) {
1646 /* shut down the compiler thread */
Bill Buzbee5e7bfdf2010-02-08 17:08:15 -08001647 dvmCompilerShutdown();
Ben Cheng580e09e2009-10-09 11:55:30 -07001648 }
Ben Chengef00a852009-06-22 22:53:35 -07001649#endif
1650
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001651 /*
1652 * Kill any daemon threads that still exist. Actively-running threads
1653 * are likely to crash the process if they continue to execute while
1654 * the VM shuts down.
1655 */
1656 dvmSlayDaemons();
1657
Andy McFadden43eb5012010-02-01 16:56:53 -08001658 if (gDvm.verboseShutdown)
1659 LOGD("VM cleaning up\n");
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001660
1661 dvmDebuggerShutdown();
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001662 dvmProfilingShutdown();
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001663 dvmJniShutdown();
1664 dvmStringInternShutdown();
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001665 dvmThreadShutdown();
1666 dvmClassShutdown();
The Android Open Source Project99409882009-03-18 22:20:24 -07001667 dvmRegisterMapShutdown();
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001668 dvmInstanceofShutdown();
1669 dvmInlineNativeShutdown();
1670 dvmGcShutdown();
1671 dvmAllocTrackerShutdown();
1672 dvmPropertiesShutdown();
1673
1674 /* these must happen AFTER dvmClassShutdown has walked through class data */
1675 dvmNativeShutdown();
1676 dvmInternalNativeShutdown();
1677
Andy McFadden65a54dc2011-01-27 17:01:54 -08001678 dvmFreeInlineSubsTable();
1679
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001680 free(gDvm.bootClassPathStr);
1681 free(gDvm.classPathStr);
1682
1683 freeAssertionCtrl();
1684
1685 /*
1686 * We want valgrind to report anything we forget to free as "definitely
1687 * lost". If there's a pointer in the global chunk, it would be reported
1688 * as "still reachable". Erasing the memory fixes this.
1689 *
1690 * This must be erased to zero if we want to restart the VM within this
1691 * process.
1692 */
1693 memset(&gDvm, 0xcd, sizeof(gDvm));
1694}
1695
1696
1697/*
1698 * fprintf() wrapper that calls through the JNI-specified vfprintf hook if
1699 * one was specified.
1700 */
1701int dvmFprintf(FILE* fp, const char* format, ...)
1702{
1703 va_list args;
1704 int result;
1705
1706 va_start(args, format);
1707 if (gDvm.vfprintfHook != NULL)
1708 result = (*gDvm.vfprintfHook)(fp, format, args);
1709 else
1710 result = vfprintf(fp, format, args);
1711 va_end(args);
1712
1713 return result;
1714}
1715
Elliott Hughesabd4f6e2011-03-25 11:58:52 -07001716#ifdef __GLIBC__
1717#include <execinfo.h>
1718/*
1719 * glibc-only stack dump function. Requires link with "--export-dynamic".
1720 *
1721 * TODO: move this into libs/cutils and make it work for all platforms.
1722 */
Carl Shapiro1e1433e2011-04-20 16:51:38 -07001723void dvmPrintNativeBackTrace()
Elliott Hughesabd4f6e2011-03-25 11:58:52 -07001724{
1725 size_t MAX_STACK_FRAMES = 64;
1726 void* stackFrames[MAX_STACK_FRAMES];
1727 size_t frameCount = backtrace(stackFrames, MAX_STACK_FRAMES);
1728
1729 /*
1730 * TODO: in practice, we may find that we should use backtrace_symbols_fd
1731 * to avoid allocation, rather than use our own custom formatting.
1732 */
1733 char** strings = backtrace_symbols(stackFrames, frameCount);
1734 if (strings == NULL) {
1735 LOGE("backtrace_symbols failed: %s", strerror(errno));
1736 return;
1737 }
1738
1739 size_t i;
1740 for (i = 0; i < frameCount; ++i) {
Elliott Hughes045736c2011-03-25 13:53:43 -07001741 LOGW("#%-2d %s", i, strings[i]);
Elliott Hughesabd4f6e2011-03-25 11:58:52 -07001742 }
1743 free(strings);
1744}
1745#else
Carl Shapiro1e1433e2011-04-20 16:51:38 -07001746void dvmPrintNativeBackTrace() {
Elliott Hughesabd4f6e2011-03-25 11:58:52 -07001747 /* Hopefully, you're on an Android device and debuggerd will do this. */
1748}
1749#endif
1750
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001751/*
1752 * Abort the VM. We get here on fatal errors. Try very hard not to use
1753 * this; whenever possible, return an error to somebody responsible.
1754 */
Carl Shapiro1e1433e2011-04-20 16:51:38 -07001755void dvmAbort()
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001756{
1757 LOGE("VM aborting\n");
1758
1759 fflush(NULL); // flush all open file buffers
1760
1761 /* JNI-supplied abort hook gets right of first refusal */
1762 if (gDvm.abortHook != NULL)
1763 (*gDvm.abortHook)();
1764
1765 /*
Elliott Hughesabd4f6e2011-03-25 11:58:52 -07001766 * On the device, debuggerd will give us a stack trace.
1767 * On the host, we have to help ourselves.
1768 */
1769 dvmPrintNativeBackTrace();
1770
1771 /*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001772 * If we call abort(), all threads in the process receives a SIBABRT.
1773 * debuggerd dumps the stack trace of the main thread, whether or not
1774 * that was the thread that failed.
1775 *
1776 * By stuffing a value into a bogus address, we cause a segmentation
1777 * fault in the current thread, and get a useful log from debuggerd.
1778 * We can also trivially tell the difference between a VM crash and
1779 * a deliberate abort by looking at the fault address.
1780 */
1781 *((char*)0xdeadd00d) = 38;
1782 abort();
1783
1784 /* notreached */
1785}