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