1 /* 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.system.VMDebug 19 */ 20 #include "Dalvik.h" 21 #include "alloc/HeapSource.h" 22 #include "native/InternalNativePriv.h" 23 #include "hprof/Hprof.h" 24 25 #include <string.h> 26 #include <unistd.h> 27 28 29 /* 30 * Extracts the fd from a FileDescriptor object. 31 * 32 * If an error is encountered, or the extracted descriptor is numerically 33 * invalid, this returns -1 with an exception raised. 34 */ 35 static int getFileDescriptor(Object* obj) 36 { 37 assert(obj != NULL); 38 assert(strcmp(obj->clazz->descriptor, "Ljava/io/FileDescriptor;") == 0); 39 40 int fd = dvmGetFieldInt(obj, gDvm.offJavaIoFileDescriptor_descriptor); 41 if (fd < 0) { 42 dvmThrowRuntimeException("Invalid file descriptor"); 43 return -1; 44 } 45 46 return fd; 47 } 48 49 /* 50 * static String[] getVmFeatureList() 51 * 52 * Return a set of strings describing available VM features (this is chiefly 53 * of interest to DDMS). 54 */ 55 static void Dalvik_dalvik_system_VMDebug_getVmFeatureList(const u4* args, JValue* pResult) { 56 std::vector<std::string> features; 57 features.push_back("method-trace-profiling"); 58 features.push_back("method-trace-profiling-streaming"); 59 features.push_back("method-sample-profiling"); 60 features.push_back("hprof-heap-dump"); 61 features.push_back("hprof-heap-dump-streaming"); 62 63 ArrayObject* result = dvmCreateStringArray(features); 64 dvmReleaseTrackedAlloc((Object*) result, dvmThreadSelf()); 65 RETURN_PTR(result); 66 } 67 68 /* These must match the values in dalvik.system.VMDebug. 69 */ 70 enum { 71 KIND_ALLOCATED_OBJECTS = 1<<0, 72 KIND_ALLOCATED_BYTES = 1<<1, 73 KIND_FREED_OBJECTS = 1<<2, 74 KIND_FREED_BYTES = 1<<3, 75 KIND_GC_INVOCATIONS = 1<<4, 76 KIND_CLASS_INIT_COUNT = 1<<5, 77 KIND_CLASS_INIT_TIME = 1<<6, 78 79 /* These values exist for backward compatibility. */ 80 KIND_EXT_ALLOCATED_OBJECTS = 1<<12, 81 KIND_EXT_ALLOCATED_BYTES = 1<<13, 82 KIND_EXT_FREED_OBJECTS = 1<<14, 83 KIND_EXT_FREED_BYTES = 1<<15, 84 85 KIND_GLOBAL_ALLOCATED_OBJECTS = KIND_ALLOCATED_OBJECTS, 86 KIND_GLOBAL_ALLOCATED_BYTES = KIND_ALLOCATED_BYTES, 87 KIND_GLOBAL_FREED_OBJECTS = KIND_FREED_OBJECTS, 88 KIND_GLOBAL_FREED_BYTES = KIND_FREED_BYTES, 89 KIND_GLOBAL_GC_INVOCATIONS = KIND_GC_INVOCATIONS, 90 KIND_GLOBAL_CLASS_INIT_COUNT = KIND_CLASS_INIT_COUNT, 91 KIND_GLOBAL_CLASS_INIT_TIME = KIND_CLASS_INIT_TIME, 92 93 KIND_THREAD_ALLOCATED_OBJECTS = KIND_ALLOCATED_OBJECTS << 16, 94 KIND_THREAD_ALLOCATED_BYTES = KIND_ALLOCATED_BYTES << 16, 95 KIND_THREAD_FREED_OBJECTS = KIND_FREED_OBJECTS << 16, 96 KIND_THREAD_FREED_BYTES = KIND_FREED_BYTES << 16, 97 98 KIND_THREAD_GC_INVOCATIONS = KIND_GC_INVOCATIONS << 16, 99 100 // TODO: failedAllocCount, failedAllocSize 101 }; 102 103 #define KIND_ALL_COUNTS 0xffffffff 104 105 /* 106 * Zero out the specified fields. 107 */ 108 static void clearAllocProfStateFields(AllocProfState *allocProf, 109 unsigned int kinds) 110 { 111 if (kinds & KIND_ALLOCATED_OBJECTS) { 112 allocProf->allocCount = 0; 113 } 114 if (kinds & KIND_ALLOCATED_BYTES) { 115 allocProf->allocSize = 0; 116 } 117 if (kinds & KIND_FREED_OBJECTS) { 118 allocProf->freeCount = 0; 119 } 120 if (kinds & KIND_FREED_BYTES) { 121 allocProf->freeSize = 0; 122 } 123 if (kinds & KIND_GC_INVOCATIONS) { 124 allocProf->gcCount = 0; 125 } 126 if (kinds & KIND_CLASS_INIT_COUNT) { 127 allocProf->classInitCount = 0; 128 } 129 if (kinds & KIND_CLASS_INIT_TIME) { 130 allocProf->classInitTime = 0; 131 } 132 } 133 134 /* 135 * static void startAllocCounting() 136 * 137 * Reset the counters and enable counting. 138 * 139 * TODO: this currently only resets the per-thread counters for the current 140 * thread. If we actually start using the per-thread counters we'll 141 * probably want to fix this. 142 */ 143 static void Dalvik_dalvik_system_VMDebug_startAllocCounting(const u4* args, 144 JValue* pResult) 145 { 146 UNUSED_PARAMETER(args); 147 148 clearAllocProfStateFields(&gDvm.allocProf, KIND_ALL_COUNTS); 149 clearAllocProfStateFields(&dvmThreadSelf()->allocProf, KIND_ALL_COUNTS); 150 dvmStartAllocCounting(); 151 RETURN_VOID(); 152 } 153 154 /* 155 * public static void stopAllocCounting() 156 */ 157 static void Dalvik_dalvik_system_VMDebug_stopAllocCounting(const u4* args, 158 JValue* pResult) 159 { 160 UNUSED_PARAMETER(args); 161 162 dvmStopAllocCounting(); 163 RETURN_VOID(); 164 } 165 166 /* 167 * private static int getAllocCount(int kind) 168 */ 169 static void Dalvik_dalvik_system_VMDebug_getAllocCount(const u4* args, 170 JValue* pResult) 171 { 172 AllocProfState *allocProf; 173 unsigned int kind = args[0]; 174 if (kind < (1<<16)) { 175 allocProf = &gDvm.allocProf; 176 } else { 177 allocProf = &dvmThreadSelf()->allocProf; 178 kind >>= 16; 179 } 180 switch (kind) { 181 case KIND_ALLOCATED_OBJECTS: 182 pResult->i = allocProf->allocCount; 183 break; 184 case KIND_ALLOCATED_BYTES: 185 pResult->i = allocProf->allocSize; 186 break; 187 case KIND_FREED_OBJECTS: 188 pResult->i = allocProf->freeCount; 189 break; 190 case KIND_FREED_BYTES: 191 pResult->i = allocProf->freeSize; 192 break; 193 case KIND_GC_INVOCATIONS: 194 pResult->i = allocProf->gcCount; 195 break; 196 case KIND_CLASS_INIT_COUNT: 197 pResult->i = allocProf->classInitCount; 198 break; 199 case KIND_CLASS_INIT_TIME: 200 /* convert nsec to usec, reduce to 32 bits */ 201 pResult->i = (int) (allocProf->classInitTime / 1000); 202 break; 203 case KIND_EXT_ALLOCATED_OBJECTS: 204 case KIND_EXT_ALLOCATED_BYTES: 205 case KIND_EXT_FREED_OBJECTS: 206 case KIND_EXT_FREED_BYTES: 207 pResult->i = 0; /* backward compatibility */ 208 break; 209 default: 210 assert(false); 211 pResult->i = -1; 212 } 213 } 214 215 /* 216 * public static void resetAllocCount(int kinds) 217 */ 218 static void Dalvik_dalvik_system_VMDebug_resetAllocCount(const u4* args, 219 JValue* pResult) 220 { 221 unsigned int kinds = args[0]; 222 clearAllocProfStateFields(&gDvm.allocProf, kinds & 0xffff); 223 clearAllocProfStateFields(&dvmThreadSelf()->allocProf, kinds >> 16); 224 RETURN_VOID(); 225 } 226 227 /* 228 * static void startMethodTracingDdmsImpl(int bufferSize, int flags, 229 * boolean samplingEnabled, int intervalUs) 230 * 231 * Start method trace profiling, sending results directly to DDMS. 232 */ 233 static void Dalvik_dalvik_system_VMDebug_startMethodTracingDdmsImpl(const u4* args, 234 JValue* pResult) 235 { 236 int bufferSize = args[0]; 237 int flags = args[1]; 238 bool samplingEnabled = args[2]; 239 int intervalUs = args[3]; 240 dvmMethodTraceStart("[DDMS]", -1, bufferSize, flags, true, samplingEnabled, 241 intervalUs); 242 RETURN_VOID(); 243 } 244 245 /* 246 * static void startMethodTracingFd(String traceFileName, FileDescriptor fd, 247 * int bufferSize, int flags) 248 * 249 * Start method trace profiling, sending results to a file descriptor. 250 */ 251 static void Dalvik_dalvik_system_VMDebug_startMethodTracingFd(const u4* args, 252 JValue* pResult) 253 { 254 StringObject* traceFileStr = (StringObject*) args[0]; 255 Object* traceFd = (Object*) args[1]; 256 int bufferSize = args[2]; 257 int flags = args[3]; 258 259 int origFd = getFileDescriptor(traceFd); 260 if (origFd < 0) 261 RETURN_VOID(); 262 263 int fd = dup(origFd); 264 if (fd < 0) { 265 dvmThrowExceptionFmt(gDvm.exRuntimeException, 266 "dup(%d) failed: %s", origFd, strerror(errno)); 267 RETURN_VOID(); 268 } 269 270 char* traceFileName = dvmCreateCstrFromString(traceFileStr); 271 if (traceFileName == NULL) { 272 RETURN_VOID(); 273 } 274 275 dvmMethodTraceStart(traceFileName, fd, bufferSize, flags, false, false, 0); 276 free(traceFileName); 277 RETURN_VOID(); 278 } 279 280 /* 281 * static void startMethodTracingFilename(String traceFileName, int bufferSize, 282 * int flags) 283 * 284 * Start method trace profiling, sending results to a file. 285 */ 286 static void Dalvik_dalvik_system_VMDebug_startMethodTracingFilename(const u4* args, 287 JValue* pResult) 288 { 289 StringObject* traceFileStr = (StringObject*) args[0]; 290 int bufferSize = args[1]; 291 int flags = args[2]; 292 293 char* traceFileName = dvmCreateCstrFromString(traceFileStr); 294 if (traceFileName == NULL) { 295 RETURN_VOID(); 296 } 297 298 dvmMethodTraceStart(traceFileName, -1, bufferSize, flags, false, false, 0); 299 free(traceFileName); 300 RETURN_VOID(); 301 } 302 303 /* 304 * static int getMethodTracingMode() 305 * 306 * Determine whether method tracing is currently active and what type is active. 307 */ 308 static void Dalvik_dalvik_system_VMDebug_getMethodTracingMode(const u4* args, 309 JValue* pResult) 310 { 311 UNUSED_PARAMETER(args); 312 313 RETURN_INT(dvmGetMethodTracingMode()); 314 } 315 316 /* 317 * static void stopMethodTracing() 318 * 319 * Stop method tracing. 320 */ 321 static void Dalvik_dalvik_system_VMDebug_stopMethodTracing(const u4* args, 322 JValue* pResult) 323 { 324 UNUSED_PARAMETER(args); 325 326 dvmMethodTraceStop(); 327 RETURN_VOID(); 328 } 329 330 /* 331 * static void startEmulatorTracing() 332 * 333 * Start sending method trace info to the emulator. 334 */ 335 static void Dalvik_dalvik_system_VMDebug_startEmulatorTracing(const u4* args, 336 JValue* pResult) 337 { 338 UNUSED_PARAMETER(args); 339 340 dvmEmulatorTraceStart(); 341 RETURN_VOID(); 342 } 343 344 /* 345 * static void stopEmulatorTracing() 346 * 347 * Start sending method trace info to the emulator. 348 */ 349 static void Dalvik_dalvik_system_VMDebug_stopEmulatorTracing(const u4* args, 350 JValue* pResult) 351 { 352 UNUSED_PARAMETER(args); 353 354 dvmEmulatorTraceStop(); 355 RETURN_VOID(); 356 } 357 358 /* 359 * static boolean isDebuggerConnected() 360 * 361 * Returns "true" if a debugger is attached. 362 */ 363 static void Dalvik_dalvik_system_VMDebug_isDebuggerConnected(const u4* args, 364 JValue* pResult) 365 { 366 UNUSED_PARAMETER(args); 367 368 RETURN_BOOLEAN(dvmDbgIsDebuggerConnected()); 369 } 370 371 /* 372 * static boolean isDebuggingEnabled() 373 * 374 * Returns "true" if debugging is enabled. 375 */ 376 static void Dalvik_dalvik_system_VMDebug_isDebuggingEnabled(const u4* args, 377 JValue* pResult) 378 { 379 UNUSED_PARAMETER(args); 380 381 RETURN_BOOLEAN(gDvm.jdwpConfigured); 382 } 383 384 /* 385 * static long lastDebuggerActivity() 386 * 387 * Returns the time, in msec, since we last had an interaction with the 388 * debugger (send or receive). 389 */ 390 static void Dalvik_dalvik_system_VMDebug_lastDebuggerActivity(const u4* args, 391 JValue* pResult) 392 { 393 UNUSED_PARAMETER(args); 394 395 RETURN_LONG(dvmDbgLastDebuggerActivity()); 396 } 397 398 /* 399 * static void startInstructionCounting() 400 */ 401 static void Dalvik_dalvik_system_VMDebug_startInstructionCounting(const u4* args, 402 JValue* pResult) 403 { 404 dvmStartInstructionCounting(); 405 RETURN_VOID(); 406 } 407 408 /* 409 * static void stopInstructionCounting() 410 */ 411 static void Dalvik_dalvik_system_VMDebug_stopInstructionCounting(const u4* args, 412 JValue* pResult) 413 { 414 dvmStopInstructionCounting(); 415 RETURN_VOID(); 416 } 417 418 /* 419 * static boolean getInstructionCount(int[] counts) 420 * 421 * Grab a copy of the global instruction count array. 422 * 423 * Since the instruction counts aren't synchronized, we use sched_yield 424 * to improve our chances of finishing without contention. (Only makes 425 * sense on a uniprocessor.) 426 */ 427 static void Dalvik_dalvik_system_VMDebug_getInstructionCount(const u4* args, 428 JValue* pResult) 429 { 430 ArrayObject* countArray = (ArrayObject*) args[0]; 431 432 if (countArray != NULL) { 433 int* storage = (int*)(void*)countArray->contents; 434 u4 length = countArray->length; 435 436 /* 437 * Ensure that we copy at most kNumPackedOpcodes 438 * elements, but no more than the length of the given array. 439 */ 440 if (length > kNumPackedOpcodes) { 441 length = kNumPackedOpcodes; 442 } 443 444 sched_yield(); 445 memcpy(storage, gDvm.executedInstrCounts, length * sizeof(int)); 446 } 447 448 RETURN_VOID(); 449 } 450 451 /* 452 * static boolean resetInstructionCount() 453 * 454 * Reset the instruction count array. 455 */ 456 static void Dalvik_dalvik_system_VMDebug_resetInstructionCount(const u4* args, 457 JValue* pResult) 458 { 459 sched_yield(); 460 memset(gDvm.executedInstrCounts, 0, kNumPackedOpcodes * sizeof(int)); 461 RETURN_VOID(); 462 } 463 464 /* 465 * static void printLoadedClasses(int flags) 466 * 467 * Dump the list of loaded classes. 468 */ 469 static void Dalvik_dalvik_system_VMDebug_printLoadedClasses(const u4* args, 470 JValue* pResult) 471 { 472 int flags = args[0]; 473 474 dvmDumpAllClasses(flags); 475 476 RETURN_VOID(); 477 } 478 479 /* 480 * static int getLoadedClassCount() 481 * 482 * Return the number of loaded classes 483 */ 484 static void Dalvik_dalvik_system_VMDebug_getLoadedClassCount(const u4* args, 485 JValue* pResult) 486 { 487 int count; 488 489 UNUSED_PARAMETER(args); 490 491 count = dvmGetNumLoadedClasses(); 492 493 RETURN_INT(count); 494 } 495 496 /* 497 * Returns the thread-specific CPU-time clock value for the current thread, 498 * or -1 if the feature isn't supported. 499 */ 500 static void Dalvik_dalvik_system_VMDebug_threadCpuTimeNanos(const u4* args, 501 JValue* pResult) 502 { 503 jlong result; 504 505 #ifdef HAVE_POSIX_CLOCKS 506 struct timespec now; 507 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &now); 508 result = (jlong) (now.tv_sec*1000000000LL + now.tv_nsec); 509 #else 510 result = (jlong) -1; 511 #endif 512 513 RETURN_LONG(result); 514 } 515 516 /* 517 * static void dumpHprofData(String fileName, FileDescriptor fd) 518 * 519 * Cause "hprof" data to be dumped. We can throw an IOException if an 520 * error occurs during file handling. 521 */ 522 static void Dalvik_dalvik_system_VMDebug_dumpHprofData(const u4* args, 523 JValue* pResult) 524 { 525 StringObject* fileNameStr = (StringObject*) args[0]; 526 Object* fileDescriptor = (Object*) args[1]; 527 char* fileName; 528 int result; 529 530 /* 531 * Only one of these may be NULL. 532 */ 533 if (fileNameStr == NULL && fileDescriptor == NULL) { 534 dvmThrowNullPointerException("fileName == null && fd == null"); 535 RETURN_VOID(); 536 } 537 538 if (fileNameStr != NULL) { 539 fileName = dvmCreateCstrFromString(fileNameStr); 540 if (fileName == NULL) { 541 /* unexpected -- malloc failure? */ 542 dvmThrowRuntimeException("malloc failure?"); 543 RETURN_VOID(); 544 } 545 } else { 546 fileName = strdup("[fd]"); 547 } 548 549 int fd = -1; 550 if (fileDescriptor != NULL) { 551 fd = getFileDescriptor(fileDescriptor); 552 if (fd < 0) { 553 free(fileName); 554 RETURN_VOID(); 555 } 556 } 557 558 result = hprofDumpHeap(fileName, fd, false); 559 free(fileName); 560 561 if (result != 0) { 562 /* ideally we'd throw something more specific based on actual failure */ 563 dvmThrowRuntimeException( 564 "Failure during heap dump; check log output for details"); 565 RETURN_VOID(); 566 } 567 568 RETURN_VOID(); 569 } 570 571 /* 572 * static void dumpHprofDataDdms() 573 * 574 * Cause "hprof" data to be computed and sent directly to DDMS. 575 */ 576 static void Dalvik_dalvik_system_VMDebug_dumpHprofDataDdms(const u4* args, 577 JValue* pResult) 578 { 579 int result; 580 581 result = hprofDumpHeap("[DDMS]", -1, true); 582 583 if (result != 0) { 584 /* ideally we'd throw something more specific based on actual failure */ 585 dvmThrowRuntimeException( 586 "Failure during heap dump; check log output for details"); 587 RETURN_VOID(); 588 } 589 590 RETURN_VOID(); 591 } 592 593 /* 594 * static boolean cacheRegisterMap(String classAndMethodDescr) 595 * 596 * If the specified class is loaded, and the named method exists, ensure 597 * that the method's register map is ready for use. If the class/method 598 * cannot be found, nothing happens. 599 * 600 * This can improve the zygote's sharing of compressed register maps. Do 601 * this after class preloading. 602 * 603 * Returns true if the register map is cached and ready, either as a result 604 * of this call or earlier activity. Returns false if the class isn't loaded, 605 * if the method couldn't be found, or if the method has no register map. 606 * 607 * (Uncomment logs in dvmGetExpandedRegisterMap0() to gather stats.) 608 */ 609 static void Dalvik_dalvik_system_VMDebug_cacheRegisterMap(const u4* args, 610 JValue* pResult) 611 { 612 StringObject* classAndMethodDescStr = (StringObject*) args[0]; 613 ClassObject* clazz; 614 bool result = false; 615 616 if (classAndMethodDescStr == NULL) { 617 dvmThrowNullPointerException("classAndMethodDesc == null"); 618 RETURN_VOID(); 619 } 620 621 char* classAndMethodDesc = NULL; 622 623 /* 624 * Pick the string apart. We have a local copy, so just modify it 625 * in place. 626 */ 627 classAndMethodDesc = dvmCreateCstrFromString(classAndMethodDescStr); 628 629 char* methodName = strchr(classAndMethodDesc, '.'); 630 if (methodName == NULL) { 631 dvmThrowRuntimeException("method name not found in string"); 632 RETURN_VOID(); 633 } 634 *methodName++ = '\0'; 635 636 char* methodDescr = strchr(methodName, ':'); 637 if (methodDescr == NULL) { 638 dvmThrowRuntimeException("method descriptor not found in string"); 639 RETURN_VOID(); 640 } 641 *methodDescr++ = '\0'; 642 643 //ALOGD("GOT: %s %s %s", classAndMethodDesc, methodName, methodDescr); 644 645 /* 646 * Find the class, but only if it's already loaded. 647 */ 648 clazz = dvmLookupClass(classAndMethodDesc, NULL, false); 649 if (clazz == NULL) { 650 ALOGD("Class %s not found in bootstrap loader", classAndMethodDesc); 651 goto bail; 652 } 653 654 Method* method; 655 656 /* 657 * Find the method, which could be virtual or direct, defined directly 658 * or inherited. 659 */ 660 if (methodName[0] == '<') { 661 /* 662 * Constructor or class initializer. Only need to examine the 663 * "direct" list, and don't need to search up the class hierarchy. 664 */ 665 method = dvmFindDirectMethodByDescriptor(clazz, methodName, 666 methodDescr); 667 } else { 668 /* 669 * Try both lists, and scan up the tree. 670 */ 671 method = dvmFindVirtualMethodHierByDescriptor(clazz, methodName, 672 methodDescr); 673 if (method == NULL) { 674 method = dvmFindDirectMethodHierByDescriptor(clazz, methodName, 675 methodDescr); 676 } 677 } 678 679 if (method != NULL) { 680 /* 681 * Got it. See if there's a register map here. 682 */ 683 const RegisterMap* pMap; 684 pMap = dvmGetExpandedRegisterMap(method); 685 if (pMap == NULL) { 686 ALOGV("No map for %s.%s %s", 687 classAndMethodDesc, methodName, methodDescr); 688 } else { 689 ALOGV("Found map %s.%s %s", 690 classAndMethodDesc, methodName, methodDescr); 691 result = true; 692 } 693 } else { 694 ALOGV("Unable to find %s.%s %s", 695 classAndMethodDesc, methodName, methodDescr); 696 } 697 698 bail: 699 free(classAndMethodDesc); 700 RETURN_BOOLEAN(result); 701 } 702 703 /* 704 * static void dumpReferenceTables() 705 */ 706 static void Dalvik_dalvik_system_VMDebug_dumpReferenceTables(const u4* args, 707 JValue* pResult) 708 { 709 UNUSED_PARAMETER(args); 710 UNUSED_PARAMETER(pResult); 711 712 ALOGI("--- reference table dump ---"); 713 dvmDumpJniReferenceTables(); 714 // could dump thread's internalLocalRefTable, probably not useful 715 // ditto for thread's jniMonitorRefTable 716 ALOGI("---"); 717 RETURN_VOID(); 718 } 719 720 /* 721 * static void crash() 722 * 723 * Dump the current thread's interpreted stack and abort the VM. Useful 724 * for seeing both interpreted and native stack traces. 725 * 726 * (Might want to restrict this to debuggable processes as a security 727 * measure, or check SecurityManager.checkExit().) 728 */ 729 static void Dalvik_dalvik_system_VMDebug_crash(const u4* args, 730 JValue* pResult) 731 { 732 UNUSED_PARAMETER(args); 733 UNUSED_PARAMETER(pResult); 734 735 ALOGW("Crashing VM on request"); 736 dvmDumpThread(dvmThreadSelf(), false); 737 dvmAbort(); 738 } 739 740 /* 741 * static void infopoint(int id) 742 * 743 * Provide a hook for gdb to hang to so that the VM can be stopped when 744 * user-tagged source locations are being executed. 745 */ 746 static void Dalvik_dalvik_system_VMDebug_infopoint(const u4* args, 747 JValue* pResult) 748 { 749 gDvm.nativeDebuggerActive = true; 750 751 ALOGD("VMDebug infopoint %d hit", args[0]); 752 753 gDvm.nativeDebuggerActive = false; 754 RETURN_VOID(); 755 } 756 757 static void Dalvik_dalvik_system_VMDebug_countInstancesOfClass(const u4* args, 758 JValue* pResult) 759 { 760 ClassObject* clazz = (ClassObject*)args[0]; 761 bool countAssignable = args[1]; 762 if (clazz == NULL) { 763 RETURN_LONG(0); 764 } 765 if (countAssignable) { 766 size_t count = dvmCountAssignableInstancesOfClass(clazz); 767 RETURN_LONG((long long)count); 768 } else { 769 size_t count = dvmCountInstancesOfClass(clazz); 770 RETURN_LONG((long long)count); 771 } 772 } 773 774 /* 775 * public static native void getHeapSpaceStats(long[] data) 776 */ 777 static void Dalvik_dalvik_system_VMDebug_getHeapSpaceStats(const u4* args, 778 JValue* pResult) 779 { 780 ArrayObject* dataArray = (ArrayObject*) args[0]; 781 782 if (dataArray == NULL || dataArray->length < 6) { 783 RETURN_VOID(); 784 } 785 786 jlong* arr = (jlong*)(void*)dataArray->contents; 787 788 int j = 0; 789 size_t per_heap_allocated[2]; 790 size_t per_heap_size[2]; 791 memset(per_heap_allocated, 0, sizeof(per_heap_allocated)); 792 memset(per_heap_size, 0, sizeof(per_heap_size)); 793 dvmHeapSourceGetValue(HS_BYTES_ALLOCATED, (size_t*) &per_heap_allocated, 2); 794 dvmHeapSourceGetValue(HS_FOOTPRINT, (size_t*) &per_heap_size, 2); 795 jlong heapSize = per_heap_size[0]; 796 jlong heapUsed = per_heap_allocated[0]; 797 jlong heapFree = heapSize - heapUsed; 798 jlong zygoteSize = per_heap_size[1]; 799 jlong zygoteUsed = per_heap_allocated[1]; 800 jlong zygoteFree = zygoteSize - zygoteUsed; 801 arr[j++] = heapSize; 802 arr[j++] = heapUsed; 803 arr[j++] = heapFree; 804 arr[j++] = zygoteSize; 805 arr[j++] = zygoteUsed; 806 arr[j++] = zygoteFree; 807 808 RETURN_VOID(); 809 } 810 811 const DalvikNativeMethod dvm_dalvik_system_VMDebug[] = { 812 { "getVmFeatureList", "()[Ljava/lang/String;", 813 Dalvik_dalvik_system_VMDebug_getVmFeatureList }, 814 { "getAllocCount", "(I)I", 815 Dalvik_dalvik_system_VMDebug_getAllocCount }, 816 { "getHeapSpaceStats", "([J)V", 817 Dalvik_dalvik_system_VMDebug_getHeapSpaceStats }, 818 { "resetAllocCount", "(I)V", 819 Dalvik_dalvik_system_VMDebug_resetAllocCount }, 820 { "startAllocCounting", "()V", 821 Dalvik_dalvik_system_VMDebug_startAllocCounting }, 822 { "stopAllocCounting", "()V", 823 Dalvik_dalvik_system_VMDebug_stopAllocCounting }, 824 { "startMethodTracingDdmsImpl", "(IIZI)V", 825 Dalvik_dalvik_system_VMDebug_startMethodTracingDdmsImpl }, 826 { "startMethodTracingFd", "(Ljava/lang/String;Ljava/io/FileDescriptor;II)V", 827 Dalvik_dalvik_system_VMDebug_startMethodTracingFd }, 828 { "startMethodTracingFilename", "(Ljava/lang/String;II)V", 829 Dalvik_dalvik_system_VMDebug_startMethodTracingFilename }, 830 { "getMethodTracingMode", "()I", 831 Dalvik_dalvik_system_VMDebug_getMethodTracingMode }, 832 { "stopMethodTracing", "()V", 833 Dalvik_dalvik_system_VMDebug_stopMethodTracing }, 834 { "startEmulatorTracing", "()V", 835 Dalvik_dalvik_system_VMDebug_startEmulatorTracing }, 836 { "stopEmulatorTracing", "()V", 837 Dalvik_dalvik_system_VMDebug_stopEmulatorTracing }, 838 { "startInstructionCounting", "()V", 839 Dalvik_dalvik_system_VMDebug_startInstructionCounting }, 840 { "stopInstructionCounting", "()V", 841 Dalvik_dalvik_system_VMDebug_stopInstructionCounting }, 842 { "resetInstructionCount", "()V", 843 Dalvik_dalvik_system_VMDebug_resetInstructionCount }, 844 { "getInstructionCount", "([I)V", 845 Dalvik_dalvik_system_VMDebug_getInstructionCount }, 846 { "isDebuggerConnected", "()Z", 847 Dalvik_dalvik_system_VMDebug_isDebuggerConnected }, 848 { "isDebuggingEnabled", "()Z", 849 Dalvik_dalvik_system_VMDebug_isDebuggingEnabled }, 850 { "lastDebuggerActivity", "()J", 851 Dalvik_dalvik_system_VMDebug_lastDebuggerActivity }, 852 { "printLoadedClasses", "(I)V", 853 Dalvik_dalvik_system_VMDebug_printLoadedClasses }, 854 { "getLoadedClassCount", "()I", 855 Dalvik_dalvik_system_VMDebug_getLoadedClassCount }, 856 { "threadCpuTimeNanos", "()J", 857 Dalvik_dalvik_system_VMDebug_threadCpuTimeNanos }, 858 { "dumpHprofData", "(Ljava/lang/String;Ljava/io/FileDescriptor;)V", 859 Dalvik_dalvik_system_VMDebug_dumpHprofData }, 860 { "dumpHprofDataDdms", "()V", 861 Dalvik_dalvik_system_VMDebug_dumpHprofDataDdms }, 862 { "cacheRegisterMap", "(Ljava/lang/String;)Z", 863 Dalvik_dalvik_system_VMDebug_cacheRegisterMap }, 864 { "dumpReferenceTables", "()V", 865 Dalvik_dalvik_system_VMDebug_dumpReferenceTables }, 866 { "crash", "()V", 867 Dalvik_dalvik_system_VMDebug_crash }, 868 { "infopoint", "(I)V", 869 Dalvik_dalvik_system_VMDebug_infopoint }, 870 { "countInstancesOfClass", "(Ljava/lang/Class;Z)J", 871 Dalvik_dalvik_system_VMDebug_countInstancesOfClass }, 872 { NULL, NULL, NULL }, 873 }; 874