Debug.java revision 50f65404fba47225316cb24e53a8e0a3de340fe0
1/* 2 * Copyright (C) 2007 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 17package android.os; 18 19import com.android.internal.util.FastPrintWriter; 20import com.android.internal.util.TypedProperties; 21 22import android.util.Log; 23 24import java.io.FileDescriptor; 25import java.io.FileNotFoundException; 26import java.io.FileOutputStream; 27import java.io.FileReader; 28import java.io.IOException; 29import java.io.PrintWriter; 30import java.io.Reader; 31import java.lang.reflect.Field; 32import java.lang.reflect.Modifier; 33import java.lang.annotation.Target; 34import java.lang.annotation.ElementType; 35import java.lang.annotation.Retention; 36import java.lang.annotation.RetentionPolicy; 37import java.util.Map; 38 39import org.apache.harmony.dalvik.ddmc.Chunk; 40import org.apache.harmony.dalvik.ddmc.ChunkHandler; 41import org.apache.harmony.dalvik.ddmc.DdmServer; 42 43import dalvik.bytecode.OpcodeInfo; 44import dalvik.system.VMDebug; 45 46 47/** 48 * Provides various debugging methods for Android applications, including 49 * tracing and allocation counts. 50 * <p><strong>Logging Trace Files</strong></p> 51 * <p>Debug can create log files that give details about an application, such as 52 * a call stack and start/stop times for any running methods. See <a 53href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for 54 * information about reading trace files. To start logging trace files, call one 55 * of the startMethodTracing() methods. To stop tracing, call 56 * {@link #stopMethodTracing()}. 57 */ 58public final class Debug 59{ 60 private static final String TAG = "Debug"; 61 62 /** 63 * Flags for startMethodTracing(). These can be ORed together. 64 * 65 * TRACE_COUNT_ALLOCS adds the results from startAllocCounting to the 66 * trace key file. 67 * 68 * @deprecated Accurate counting is a burden on the runtime and may be removed. 69 */ 70 @Deprecated 71 public static final int TRACE_COUNT_ALLOCS = VMDebug.TRACE_COUNT_ALLOCS; 72 73 /** 74 * Flags for printLoadedClasses(). Default behavior is to only show 75 * the class name. 76 */ 77 public static final int SHOW_FULL_DETAIL = 1; 78 public static final int SHOW_CLASSLOADER = (1 << 1); 79 public static final int SHOW_INITIALIZED = (1 << 2); 80 81 // set/cleared by waitForDebugger() 82 private static volatile boolean mWaiting = false; 83 84 private Debug() {} 85 86 /* 87 * How long to wait for the debugger to finish sending requests. I've 88 * seen this hit 800msec on the device while waiting for a response 89 * to travel over USB and get processed, so we take that and add 90 * half a second. 91 */ 92 private static final int MIN_DEBUGGER_IDLE = 1300; // msec 93 94 /* how long to sleep when polling for activity */ 95 private static final int SPIN_DELAY = 200; // msec 96 97 /** 98 * Default trace file path and file 99 */ 100 private static final String DEFAULT_TRACE_PATH_PREFIX = 101 Environment.getLegacyExternalStorageDirectory().getPath() + "/"; 102 private static final String DEFAULT_TRACE_BODY = "dmtrace"; 103 private static final String DEFAULT_TRACE_EXTENSION = ".trace"; 104 private static final String DEFAULT_TRACE_FILE_PATH = 105 DEFAULT_TRACE_PATH_PREFIX + DEFAULT_TRACE_BODY 106 + DEFAULT_TRACE_EXTENSION; 107 108 109 /** 110 * This class is used to retrieved various statistics about the memory mappings for this 111 * process. The returned info is broken down by dalvik, native, and other. All results are in kB. 112 */ 113 public static class MemoryInfo implements Parcelable { 114 /** The proportional set size for dalvik heap. (Doesn't include other Dalvik overhead.) */ 115 public int dalvikPss; 116 /** The proportional set size that is swappable for dalvik heap. */ 117 /** @hide We may want to expose this, eventually. */ 118 public int dalvikSwappablePss; 119 /** The private dirty pages used by dalvik heap. */ 120 public int dalvikPrivateDirty; 121 /** The shared dirty pages used by dalvik heap. */ 122 public int dalvikSharedDirty; 123 /** The private clean pages used by dalvik heap. */ 124 /** @hide We may want to expose this, eventually. */ 125 public int dalvikPrivateClean; 126 /** The shared clean pages used by dalvik heap. */ 127 /** @hide We may want to expose this, eventually. */ 128 public int dalvikSharedClean; 129 /** The dirty dalvik pages that have been swapped out. */ 130 /** @hide We may want to expose this, eventually. */ 131 public int dalvikSwappedOut; 132 133 /** The proportional set size for the native heap. */ 134 public int nativePss; 135 /** The proportional set size that is swappable for the native heap. */ 136 /** @hide We may want to expose this, eventually. */ 137 public int nativeSwappablePss; 138 /** The private dirty pages used by the native heap. */ 139 public int nativePrivateDirty; 140 /** The shared dirty pages used by the native heap. */ 141 public int nativeSharedDirty; 142 /** The private clean pages used by the native heap. */ 143 /** @hide We may want to expose this, eventually. */ 144 public int nativePrivateClean; 145 /** The shared clean pages used by the native heap. */ 146 /** @hide We may want to expose this, eventually. */ 147 public int nativeSharedClean; 148 /** The dirty native pages that have been swapped out. */ 149 /** @hide We may want to expose this, eventually. */ 150 public int nativeSwappedOut; 151 152 /** The proportional set size for everything else. */ 153 public int otherPss; 154 /** The proportional set size that is swappable for everything else. */ 155 /** @hide We may want to expose this, eventually. */ 156 public int otherSwappablePss; 157 /** The private dirty pages used by everything else. */ 158 public int otherPrivateDirty; 159 /** The shared dirty pages used by everything else. */ 160 public int otherSharedDirty; 161 /** The private clean pages used by everything else. */ 162 /** @hide We may want to expose this, eventually. */ 163 public int otherPrivateClean; 164 /** The shared clean pages used by everything else. */ 165 /** @hide We may want to expose this, eventually. */ 166 public int otherSharedClean; 167 /** The dirty pages used by anyting else that have been swapped out. */ 168 /** @hide We may want to expose this, eventually. */ 169 public int otherSwappedOut; 170 171 /** @hide */ 172 public static final int NUM_OTHER_STATS = 17; 173 174 /** @hide */ 175 public static final int NUM_DVK_STATS = 8; 176 177 /** @hide */ 178 public static final int NUM_CATEGORIES = 7; 179 180 /** @hide */ 181 public static final int offsetPss = 0; 182 /** @hide */ 183 public static final int offsetSwappablePss = 1; 184 /** @hide */ 185 public static final int offsetPrivateDirty = 2; 186 /** @hide */ 187 public static final int offsetSharedDirty = 3; 188 /** @hide */ 189 public static final int offsetPrivateClean = 4; 190 /** @hide */ 191 public static final int offsetSharedClean = 5; 192 /** @hide */ 193 public static final int offsetSwappedOut = 6; 194 195 private int[] otherStats = new int[(NUM_OTHER_STATS+NUM_DVK_STATS)*NUM_CATEGORIES]; 196 197 public MemoryInfo() { 198 } 199 200 /** 201 * Return total PSS memory usage in kB. 202 */ 203 public int getTotalPss() { 204 return dalvikPss + nativePss + otherPss; 205 } 206 207 /** 208 * @hide Return total PSS memory usage in kB. 209 */ 210 public int getTotalUss() { 211 return dalvikPrivateClean + dalvikPrivateDirty 212 + nativePrivateClean + nativePrivateDirty 213 + otherPrivateClean + otherPrivateDirty; 214 } 215 216 /** 217 * Return total PSS memory usage in kB. 218 */ 219 public int getTotalSwappablePss() { 220 return dalvikSwappablePss + nativeSwappablePss + otherSwappablePss; 221 } 222 223 /** 224 * Return total private dirty memory usage in kB. 225 */ 226 public int getTotalPrivateDirty() { 227 return dalvikPrivateDirty + nativePrivateDirty + otherPrivateDirty; 228 } 229 230 /** 231 * Return total shared dirty memory usage in kB. 232 */ 233 public int getTotalSharedDirty() { 234 return dalvikSharedDirty + nativeSharedDirty + otherSharedDirty; 235 } 236 237 /** 238 * Return total shared clean memory usage in kB. 239 */ 240 public int getTotalPrivateClean() { 241 return dalvikPrivateClean + nativePrivateClean + otherPrivateClean; 242 } 243 244 /** 245 * Return total shared clean memory usage in kB. 246 */ 247 public int getTotalSharedClean() { 248 return dalvikSharedClean + nativeSharedClean + otherSharedClean; 249 } 250 251 /** 252 * Return total swapped out memory in kB. 253 * @hide 254 */ 255 public int getTotalSwappedOut() { 256 return dalvikSwappedOut + nativeSwappedOut + otherSwappedOut; 257 } 258 259 /** @hide */ 260 public int getOtherPss(int which) { 261 return otherStats[which*NUM_CATEGORIES + offsetPss]; 262 } 263 264 265 /** @hide */ 266 public int getOtherSwappablePss(int which) { 267 return otherStats[which*NUM_CATEGORIES + offsetSwappablePss]; 268 } 269 270 271 /** @hide */ 272 public int getOtherPrivateDirty(int which) { 273 return otherStats[which*NUM_CATEGORIES + offsetPrivateDirty]; 274 } 275 276 /** @hide */ 277 public int getOtherSharedDirty(int which) { 278 return otherStats[which*NUM_CATEGORIES + offsetSharedDirty]; 279 } 280 281 /** @hide */ 282 public int getOtherPrivateClean(int which) { 283 return otherStats[which*NUM_CATEGORIES + offsetPrivateClean]; 284 } 285 286 /** @hide */ 287 public int getOtherSharedClean(int which) { 288 return otherStats[which*NUM_CATEGORIES + offsetSharedClean]; 289 } 290 291 /** @hide */ 292 public int getOtherSwappedOut(int which) { 293 return otherStats[which*NUM_CATEGORIES + offsetSwappedOut]; 294 } 295 296 /** @hide */ 297 public static String getOtherLabel(int which) { 298 switch (which) { 299 case 0: return "Dalvik Other"; 300 case 1: return "Stack"; 301 case 2: return "Cursor"; 302 case 3: return "Ashmem"; 303 case 4: return "Gfx dev"; 304 case 5: return "Other dev"; 305 case 6: return ".so mmap"; 306 case 7: return ".jar mmap"; 307 case 8: return ".apk mmap"; 308 case 9: return ".ttf mmap"; 309 case 10: return ".dex mmap"; 310 case 11: return ".oat mmap"; 311 case 12: return ".art mmap"; 312 case 13: return "Other mmap"; 313 case 14: return "EGL mtrack"; 314 case 15: return "GL mtrack"; 315 case 16: return "Other mtrack"; 316 case 17: return ".Heap"; 317 case 18: return ".LOS"; 318 case 19: return ".LinearAlloc"; 319 case 20: return ".GC"; 320 case 21: return ".JITCache"; 321 case 22: return ".Zygote"; 322 case 23: return ".NonMoving"; 323 case 24: return ".IndirectRef"; 324 default: return "????"; 325 } 326 } 327 328 public int describeContents() { 329 return 0; 330 } 331 332 public void writeToParcel(Parcel dest, int flags) { 333 dest.writeInt(dalvikPss); 334 dest.writeInt(dalvikSwappablePss); 335 dest.writeInt(dalvikPrivateDirty); 336 dest.writeInt(dalvikSharedDirty); 337 dest.writeInt(dalvikPrivateClean); 338 dest.writeInt(dalvikSharedClean); 339 dest.writeInt(dalvikSwappedOut); 340 dest.writeInt(nativePss); 341 dest.writeInt(nativeSwappablePss); 342 dest.writeInt(nativePrivateDirty); 343 dest.writeInt(nativeSharedDirty); 344 dest.writeInt(nativePrivateClean); 345 dest.writeInt(nativeSharedClean); 346 dest.writeInt(nativeSwappedOut); 347 dest.writeInt(otherPss); 348 dest.writeInt(otherSwappablePss); 349 dest.writeInt(otherPrivateDirty); 350 dest.writeInt(otherSharedDirty); 351 dest.writeInt(otherPrivateClean); 352 dest.writeInt(otherSharedClean); 353 dest.writeInt(otherSwappedOut); 354 dest.writeIntArray(otherStats); 355 } 356 357 public void readFromParcel(Parcel source) { 358 dalvikPss = source.readInt(); 359 dalvikSwappablePss = source.readInt(); 360 dalvikPrivateDirty = source.readInt(); 361 dalvikSharedDirty = source.readInt(); 362 dalvikPrivateClean = source.readInt(); 363 dalvikSharedClean = source.readInt(); 364 dalvikSwappedOut = source.readInt(); 365 nativePss = source.readInt(); 366 nativeSwappablePss = source.readInt(); 367 nativePrivateDirty = source.readInt(); 368 nativeSharedDirty = source.readInt(); 369 nativePrivateClean = source.readInt(); 370 nativeSharedClean = source.readInt(); 371 nativeSwappedOut = source.readInt(); 372 otherPss = source.readInt(); 373 otherSwappablePss = source.readInt(); 374 otherPrivateDirty = source.readInt(); 375 otherSharedDirty = source.readInt(); 376 otherPrivateClean = source.readInt(); 377 otherSharedClean = source.readInt(); 378 otherSwappedOut = source.readInt(); 379 otherStats = source.createIntArray(); 380 } 381 382 public static final Creator<MemoryInfo> CREATOR = new Creator<MemoryInfo>() { 383 public MemoryInfo createFromParcel(Parcel source) { 384 return new MemoryInfo(source); 385 } 386 public MemoryInfo[] newArray(int size) { 387 return new MemoryInfo[size]; 388 } 389 }; 390 391 private MemoryInfo(Parcel source) { 392 readFromParcel(source); 393 } 394 } 395 396 397 /** 398 * Wait until a debugger attaches. As soon as the debugger attaches, 399 * this returns, so you will need to place a breakpoint after the 400 * waitForDebugger() call if you want to start tracing immediately. 401 */ 402 public static void waitForDebugger() { 403 if (!VMDebug.isDebuggingEnabled()) { 404 //System.out.println("debugging not enabled, not waiting"); 405 return; 406 } 407 if (isDebuggerConnected()) 408 return; 409 410 // if DDMS is listening, inform them of our plight 411 System.out.println("Sending WAIT chunk"); 412 byte[] data = new byte[] { 0 }; // 0 == "waiting for debugger" 413 Chunk waitChunk = new Chunk(ChunkHandler.type("WAIT"), data, 0, 1); 414 DdmServer.sendChunk(waitChunk); 415 416 mWaiting = true; 417 while (!isDebuggerConnected()) { 418 try { Thread.sleep(SPIN_DELAY); } 419 catch (InterruptedException ie) {} 420 } 421 mWaiting = false; 422 423 System.out.println("Debugger has connected"); 424 425 /* 426 * There is no "ready to go" signal from the debugger, and we're 427 * not allowed to suspend ourselves -- the debugger expects us to 428 * be running happily, and gets confused if we aren't. We need to 429 * allow the debugger a chance to set breakpoints before we start 430 * running again. 431 * 432 * Sit and spin until the debugger has been idle for a short while. 433 */ 434 while (true) { 435 long delta = VMDebug.lastDebuggerActivity(); 436 if (delta < 0) { 437 System.out.println("debugger detached?"); 438 break; 439 } 440 441 if (delta < MIN_DEBUGGER_IDLE) { 442 System.out.println("waiting for debugger to settle..."); 443 try { Thread.sleep(SPIN_DELAY); } 444 catch (InterruptedException ie) {} 445 } else { 446 System.out.println("debugger has settled (" + delta + ")"); 447 break; 448 } 449 } 450 } 451 452 /** 453 * Returns "true" if one or more threads is waiting for a debugger 454 * to attach. 455 */ 456 public static boolean waitingForDebugger() { 457 return mWaiting; 458 } 459 460 /** 461 * Determine if a debugger is currently attached. 462 */ 463 public static boolean isDebuggerConnected() { 464 return VMDebug.isDebuggerConnected(); 465 } 466 467 /** 468 * Returns an array of strings that identify VM features. This is 469 * used by DDMS to determine what sorts of operations the VM can 470 * perform. 471 * 472 * @hide 473 */ 474 public static String[] getVmFeatureList() { 475 return VMDebug.getVmFeatureList(); 476 } 477 478 /** 479 * Change the JDWP port. 480 * 481 * @deprecated no longer needed or useful 482 */ 483 @Deprecated 484 public static void changeDebugPort(int port) {} 485 486 /** 487 * This is the pathname to the sysfs file that enables and disables 488 * tracing on the qemu emulator. 489 */ 490 private static final String SYSFS_QEMU_TRACE_STATE = "/sys/qemu_trace/state"; 491 492 /** 493 * Enable qemu tracing. For this to work requires running everything inside 494 * the qemu emulator; otherwise, this method will have no effect. The trace 495 * file is specified on the command line when the emulator is started. For 496 * example, the following command line <br /> 497 * <code>emulator -trace foo</code><br /> 498 * will start running the emulator and create a trace file named "foo". This 499 * method simply enables writing the trace records to the trace file. 500 * 501 * <p> 502 * The main differences between this and {@link #startMethodTracing()} are 503 * that tracing in the qemu emulator traces every cpu instruction of every 504 * process, including kernel code, so we have more complete information, 505 * including all context switches. We can also get more detailed information 506 * such as cache misses. The sequence of calls is determined by 507 * post-processing the instruction trace. The qemu tracing is also done 508 * without modifying the application or perturbing the timing of calls 509 * because no instrumentation is added to the application being traced. 510 * </p> 511 * 512 * <p> 513 * One limitation of using this method compared to using 514 * {@link #startMethodTracing()} on the real device is that the emulator 515 * does not model all of the real hardware effects such as memory and 516 * bus contention. The emulator also has a simple cache model and cannot 517 * capture all the complexities of a real cache. 518 * </p> 519 */ 520 public static void startNativeTracing() { 521 // Open the sysfs file for writing and write "1" to it. 522 PrintWriter outStream = null; 523 try { 524 FileOutputStream fos = new FileOutputStream(SYSFS_QEMU_TRACE_STATE); 525 outStream = new FastPrintWriter(fos); 526 outStream.println("1"); 527 } catch (Exception e) { 528 } finally { 529 if (outStream != null) 530 outStream.close(); 531 } 532 533 VMDebug.startEmulatorTracing(); 534 } 535 536 /** 537 * Stop qemu tracing. See {@link #startNativeTracing()} to start tracing. 538 * 539 * <p>Tracing can be started and stopped as many times as desired. When 540 * the qemu emulator itself is stopped then the buffered trace records 541 * are flushed and written to the trace file. In fact, it is not necessary 542 * to call this method at all; simply killing qemu is sufficient. But 543 * starting and stopping a trace is useful for examining a specific 544 * region of code.</p> 545 */ 546 public static void stopNativeTracing() { 547 VMDebug.stopEmulatorTracing(); 548 549 // Open the sysfs file for writing and write "0" to it. 550 PrintWriter outStream = null; 551 try { 552 FileOutputStream fos = new FileOutputStream(SYSFS_QEMU_TRACE_STATE); 553 outStream = new FastPrintWriter(fos); 554 outStream.println("0"); 555 } catch (Exception e) { 556 // We could print an error message here but we probably want 557 // to quietly ignore errors if we are not running in the emulator. 558 } finally { 559 if (outStream != null) 560 outStream.close(); 561 } 562 } 563 564 /** 565 * Enable "emulator traces", in which information about the current 566 * method is made available to the "emulator -trace" feature. There 567 * is no corresponding "disable" call -- this is intended for use by 568 * the framework when tracing should be turned on and left that way, so 569 * that traces captured with F9/F10 will include the necessary data. 570 * 571 * This puts the VM into "profile" mode, which has performance 572 * consequences. 573 * 574 * To temporarily enable tracing, use {@link #startNativeTracing()}. 575 */ 576 public static void enableEmulatorTraceOutput() { 577 VMDebug.startEmulatorTracing(); 578 } 579 580 /** 581 * Start method tracing with default log name and buffer size. See <a 582href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for 583 * information about reading these files. Call stopMethodTracing() to stop 584 * tracing. 585 */ 586 public static void startMethodTracing() { 587 VMDebug.startMethodTracing(DEFAULT_TRACE_FILE_PATH, 0, 0, false, 0); 588 } 589 590 /** 591 * Start method tracing, specifying the trace log file name. The trace 592 * file will be put under "/sdcard" unless an absolute path is given. 593 * See <a 594 href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for 595 * information about reading trace files. 596 * 597 * @param traceName Name for the trace log file to create. 598 * If {@code traceName} is null, this value defaults to "/sdcard/dmtrace.trace". 599 * If the files already exist, they will be truncated. 600 * If the trace file given does not end in ".trace", it will be appended for you. 601 */ 602 public static void startMethodTracing(String traceName) { 603 startMethodTracing(traceName, 0, 0); 604 } 605 606 /** 607 * Start method tracing, specifying the trace log file name and the 608 * buffer size. The trace files will be put under "/sdcard" unless an 609 * absolute path is given. See <a 610 href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for 611 * information about reading trace files. 612 * @param traceName Name for the trace log file to create. 613 * If {@code traceName} is null, this value defaults to "/sdcard/dmtrace.trace". 614 * If the files already exist, they will be truncated. 615 * If the trace file given does not end in ".trace", it will be appended for you. 616 * 617 * @param bufferSize The maximum amount of trace data we gather. If not given, it defaults to 8MB. 618 */ 619 public static void startMethodTracing(String traceName, int bufferSize) { 620 startMethodTracing(traceName, bufferSize, 0); 621 } 622 623 /** 624 * Start method tracing, specifying the trace log file name and the 625 * buffer size. The trace files will be put under "/sdcard" unless an 626 * absolute path is given. See <a 627 href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for 628 * information about reading trace files. 629 * 630 * <p> 631 * When method tracing is enabled, the VM will run more slowly than 632 * usual, so the timings from the trace files should only be considered 633 * in relative terms (e.g. was run #1 faster than run #2). The times 634 * for native methods will not change, so don't try to use this to 635 * compare the performance of interpreted and native implementations of the 636 * same method. As an alternative, consider using sampling-based method 637 * tracing via {@link #startMethodTracingSampling(String, int, int)} or 638 * "native" tracing in the emulator via {@link #startNativeTracing()}. 639 * </p> 640 * 641 * @param traceName Name for the trace log file to create. 642 * If {@code traceName} is null, this value defaults to "/sdcard/dmtrace.trace". 643 * If the files already exist, they will be truncated. 644 * If the trace file given does not end in ".trace", it will be appended for you. 645 * @param bufferSize The maximum amount of trace data we gather. If not given, it defaults to 8MB. 646 * @param flags Flags to control method tracing. The only one that is currently defined is {@link #TRACE_COUNT_ALLOCS}. 647 */ 648 public static void startMethodTracing(String traceName, int bufferSize, 649 int flags) { 650 VMDebug.startMethodTracing(fixTraceName(traceName), bufferSize, flags, false, 0); 651 } 652 653 /** 654 * Start sampling-based method tracing, specifying the trace log file name, 655 * the buffer size, and the sampling interval. The trace files will be put 656 * under "/sdcard" unless an absolute path is given. See <a 657 href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> 658 * for information about reading trace files. 659 * 660 * @param traceName Name for the trace log file to create. 661 * If {@code traceName} is null, this value defaults to "/sdcard/dmtrace.trace". 662 * If the files already exist, they will be truncated. 663 * If the trace file given does not end in ".trace", it will be appended for you. 664 * @param bufferSize The maximum amount of trace data we gather. If not given, it defaults to 8MB. 665 * @param intervalUs The amount of time between each sample in microseconds. 666 */ 667 public static void startMethodTracingSampling(String traceName, 668 int bufferSize, int intervalUs) { 669 VMDebug.startMethodTracing(fixTraceName(traceName), bufferSize, 0, true, intervalUs); 670 } 671 672 /** 673 * Formats name of trace log file for method tracing. 674 */ 675 private static String fixTraceName(String traceName) { 676 if (traceName == null) 677 traceName = DEFAULT_TRACE_FILE_PATH; 678 if (traceName.charAt(0) != '/') 679 traceName = DEFAULT_TRACE_PATH_PREFIX + traceName; 680 if (!traceName.endsWith(DEFAULT_TRACE_EXTENSION)) 681 traceName = traceName + DEFAULT_TRACE_EXTENSION; 682 683 return traceName; 684 } 685 686 /** 687 * Like startMethodTracing(String, int, int), but taking an already-opened 688 * FileDescriptor in which the trace is written. The file name is also 689 * supplied simply for logging. Makes a dup of the file descriptor. 690 * 691 * Not exposed in the SDK unless we are really comfortable with supporting 692 * this and find it would be useful. 693 * @hide 694 */ 695 public static void startMethodTracing(String traceName, FileDescriptor fd, 696 int bufferSize, int flags) { 697 VMDebug.startMethodTracing(traceName, fd, bufferSize, flags, false, 0); 698 } 699 700 /** 701 * Starts method tracing without a backing file. When stopMethodTracing 702 * is called, the result is sent directly to DDMS. (If DDMS is not 703 * attached when tracing ends, the profiling data will be discarded.) 704 * 705 * @hide 706 */ 707 public static void startMethodTracingDdms(int bufferSize, int flags, 708 boolean samplingEnabled, int intervalUs) { 709 VMDebug.startMethodTracingDdms(bufferSize, flags, samplingEnabled, intervalUs); 710 } 711 712 /** 713 * Determine whether method tracing is currently active and what type is 714 * active. 715 * 716 * @hide 717 */ 718 public static int getMethodTracingMode() { 719 return VMDebug.getMethodTracingMode(); 720 } 721 722 /** 723 * Stop method tracing. 724 */ 725 public static void stopMethodTracing() { 726 VMDebug.stopMethodTracing(); 727 } 728 729 /** 730 * Get an indication of thread CPU usage. The value returned 731 * indicates the amount of time that the current thread has spent 732 * executing code or waiting for certain types of I/O. 733 * 734 * The time is expressed in nanoseconds, and is only meaningful 735 * when compared to the result from an earlier call. Note that 736 * nanosecond resolution does not imply nanosecond accuracy. 737 * 738 * On system which don't support this operation, the call returns -1. 739 */ 740 public static long threadCpuTimeNanos() { 741 return VMDebug.threadCpuTimeNanos(); 742 } 743 744 /** 745 * Start counting the number and aggregate size of memory allocations. 746 * 747 * <p>The {@link #startAllocCounting() start} method resets the counts and enables counting. 748 * The {@link #stopAllocCounting() stop} method disables the counting so that the analysis 749 * code doesn't cause additional allocations. The various <code>get</code> methods return 750 * the specified value. And the various <code>reset</code> methods reset the specified 751 * count.</p> 752 * 753 * <p>Counts are kept for the system as a whole (global) and for each thread. 754 * The per-thread counts for threads other than the current thread 755 * are not cleared by the "reset" or "start" calls.</p> 756 * 757 * @deprecated Accurate counting is a burden on the runtime and may be removed. 758 */ 759 @Deprecated 760 public static void startAllocCounting() { 761 VMDebug.startAllocCounting(); 762 } 763 764 /** 765 * Stop counting the number and aggregate size of memory allocations. 766 * 767 * @deprecated Accurate counting is a burden on the runtime and may be removed. 768 */ 769 @Deprecated 770 public static void stopAllocCounting() { 771 VMDebug.stopAllocCounting(); 772 } 773 774 /** 775 * Returns the global count of objects allocated by the runtime between a 776 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}. 777 * 778 * @deprecated Accurate counting is a burden on the runtime and may be removed. 779 */ 780 @Deprecated 781 public static int getGlobalAllocCount() { 782 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_OBJECTS); 783 } 784 785 /** 786 * Clears the global count of objects allocated. 787 * @see #getGlobalAllocCount() 788 * 789 * @deprecated Accurate counting is a burden on the runtime and may be removed. 790 */ 791 @Deprecated 792 public static void resetGlobalAllocCount() { 793 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_OBJECTS); 794 } 795 796 /** 797 * Returns the global size, in bytes, of objects allocated by the runtime between a 798 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}. 799 * 800 * @deprecated Accurate counting is a burden on the runtime and may be removed. 801 */ 802 @Deprecated 803 public static int getGlobalAllocSize() { 804 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_BYTES); 805 } 806 807 /** 808 * Clears the global size of objects allocated. 809 * @see #getGlobalAllocSize() 810 * 811 * @deprecated Accurate counting is a burden on the runtime and may be removed. 812 */ 813 @Deprecated 814 public static void resetGlobalAllocSize() { 815 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_BYTES); 816 } 817 818 /** 819 * Returns the global count of objects freed by the runtime between a 820 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}. 821 * 822 * @deprecated Accurate counting is a burden on the runtime and may be removed. 823 */ 824 @Deprecated 825 public static int getGlobalFreedCount() { 826 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_FREED_OBJECTS); 827 } 828 829 /** 830 * Clears the global count of objects freed. 831 * @see #getGlobalFreedCount() 832 * 833 * @deprecated Accurate counting is a burden on the runtime and may be removed. 834 */ 835 @Deprecated 836 public static void resetGlobalFreedCount() { 837 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_FREED_OBJECTS); 838 } 839 840 /** 841 * Returns the global size, in bytes, of objects freed by the runtime between a 842 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}. 843 * 844 * @deprecated Accurate counting is a burden on the runtime and may be removed. 845 */ 846 @Deprecated 847 public static int getGlobalFreedSize() { 848 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_FREED_BYTES); 849 } 850 851 /** 852 * Clears the global size of objects freed. 853 * @see #getGlobalFreedSize() 854 * 855 * @deprecated Accurate counting is a burden on the runtime and may be removed. 856 */ 857 @Deprecated 858 public static void resetGlobalFreedSize() { 859 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_FREED_BYTES); 860 } 861 862 /** 863 * Returns the number of non-concurrent GC invocations between a 864 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}. 865 * 866 * @deprecated Accurate counting is a burden on the runtime and may be removed. 867 */ 868 @Deprecated 869 public static int getGlobalGcInvocationCount() { 870 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_GC_INVOCATIONS); 871 } 872 873 /** 874 * Clears the count of non-concurrent GC invocations. 875 * @see #getGlobalGcInvocationCount() 876 * 877 * @deprecated Accurate counting is a burden on the runtime and may be removed. 878 */ 879 @Deprecated 880 public static void resetGlobalGcInvocationCount() { 881 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_GC_INVOCATIONS); 882 } 883 884 /** 885 * Returns the number of classes successfully initialized (ie those that executed without 886 * throwing an exception) between a {@link #startAllocCounting() start} and 887 * {@link #stopAllocCounting() stop}. 888 * 889 * @deprecated Accurate counting is a burden on the runtime and may be removed. 890 */ 891 @Deprecated 892 public static int getGlobalClassInitCount() { 893 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_COUNT); 894 } 895 896 /** 897 * Clears the count of classes initialized. 898 * @see #getGlobalClassInitCount() 899 * 900 * @deprecated Accurate counting is a burden on the runtime and may be removed. 901 */ 902 @Deprecated 903 public static void resetGlobalClassInitCount() { 904 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_COUNT); 905 } 906 907 /** 908 * Returns the time spent successfully initializing classes between a 909 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}. 910 * 911 * @deprecated Accurate counting is a burden on the runtime and may be removed. 912 */ 913 @Deprecated 914 public static int getGlobalClassInitTime() { 915 /* cumulative elapsed time for class initialization, in usec */ 916 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_TIME); 917 } 918 919 /** 920 * Clears the count of time spent initializing classes. 921 * @see #getGlobalClassInitTime() 922 * 923 * @deprecated Accurate counting is a burden on the runtime and may be removed. 924 */ 925 @Deprecated 926 public static void resetGlobalClassInitTime() { 927 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_TIME); 928 } 929 930 /** 931 * This method exists for compatibility and always returns 0. 932 * @deprecated This method is now obsolete. 933 */ 934 @Deprecated 935 public static int getGlobalExternalAllocCount() { 936 return 0; 937 } 938 939 /** 940 * This method exists for compatibility and has no effect. 941 * @deprecated This method is now obsolete. 942 */ 943 @Deprecated 944 public static void resetGlobalExternalAllocSize() {} 945 946 /** 947 * This method exists for compatibility and has no effect. 948 * @deprecated This method is now obsolete. 949 */ 950 @Deprecated 951 public static void resetGlobalExternalAllocCount() {} 952 953 /** 954 * This method exists for compatibility and always returns 0. 955 * @deprecated This method is now obsolete. 956 */ 957 @Deprecated 958 public static int getGlobalExternalAllocSize() { 959 return 0; 960 } 961 962 /** 963 * This method exists for compatibility and always returns 0. 964 * @deprecated This method is now obsolete. 965 */ 966 @Deprecated 967 public static int getGlobalExternalFreedCount() { 968 return 0; 969 } 970 971 /** 972 * This method exists for compatibility and has no effect. 973 * @deprecated This method is now obsolete. 974 */ 975 @Deprecated 976 public static void resetGlobalExternalFreedCount() {} 977 978 /** 979 * This method exists for compatibility and has no effect. 980 * @deprecated This method is now obsolete. 981 */ 982 @Deprecated 983 public static int getGlobalExternalFreedSize() { 984 return 0; 985 } 986 987 /** 988 * This method exists for compatibility and has no effect. 989 * @deprecated This method is now obsolete. 990 */ 991 @Deprecated 992 public static void resetGlobalExternalFreedSize() {} 993 994 /** 995 * Returns the thread-local count of objects allocated by the runtime between a 996 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}. 997 * 998 * @deprecated Accurate counting is a burden on the runtime and may be removed. 999 */ 1000 @Deprecated 1001 public static int getThreadAllocCount() { 1002 return VMDebug.getAllocCount(VMDebug.KIND_THREAD_ALLOCATED_OBJECTS); 1003 } 1004 1005 /** 1006 * Clears the thread-local count of objects allocated. 1007 * @see #getThreadAllocCount() 1008 * 1009 * @deprecated Accurate counting is a burden on the runtime and may be removed. 1010 */ 1011 @Deprecated 1012 public static void resetThreadAllocCount() { 1013 VMDebug.resetAllocCount(VMDebug.KIND_THREAD_ALLOCATED_OBJECTS); 1014 } 1015 1016 /** 1017 * Returns the thread-local size of objects allocated by the runtime between a 1018 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}. 1019 * @return The allocated size in bytes. 1020 * 1021 * @deprecated Accurate counting is a burden on the runtime and may be removed. 1022 */ 1023 @Deprecated 1024 public static int getThreadAllocSize() { 1025 return VMDebug.getAllocCount(VMDebug.KIND_THREAD_ALLOCATED_BYTES); 1026 } 1027 1028 /** 1029 * Clears the thread-local count of objects allocated. 1030 * @see #getThreadAllocSize() 1031 * 1032 * @deprecated Accurate counting is a burden on the runtime and may be removed. 1033 */ 1034 @Deprecated 1035 public static void resetThreadAllocSize() { 1036 VMDebug.resetAllocCount(VMDebug.KIND_THREAD_ALLOCATED_BYTES); 1037 } 1038 1039 /** 1040 * This method exists for compatibility and has no effect. 1041 * @deprecated This method is now obsolete. 1042 */ 1043 @Deprecated 1044 public static int getThreadExternalAllocCount() { 1045 return 0; 1046 } 1047 1048 /** 1049 * This method exists for compatibility and has no effect. 1050 * @deprecated This method is now obsolete. 1051 */ 1052 @Deprecated 1053 public static void resetThreadExternalAllocCount() {} 1054 1055 /** 1056 * This method exists for compatibility and has no effect. 1057 * @deprecated This method is now obsolete. 1058 */ 1059 @Deprecated 1060 public static int getThreadExternalAllocSize() { 1061 return 0; 1062 } 1063 1064 /** 1065 * This method exists for compatibility and has no effect. 1066 * @deprecated This method is now obsolete. 1067 */ 1068 @Deprecated 1069 public static void resetThreadExternalAllocSize() {} 1070 1071 /** 1072 * Returns the number of thread-local non-concurrent GC invocations between a 1073 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}. 1074 * 1075 * @deprecated Accurate counting is a burden on the runtime and may be removed. 1076 */ 1077 @Deprecated 1078 public static int getThreadGcInvocationCount() { 1079 return VMDebug.getAllocCount(VMDebug.KIND_THREAD_GC_INVOCATIONS); 1080 } 1081 1082 /** 1083 * Clears the thread-local count of non-concurrent GC invocations. 1084 * @see #getThreadGcInvocationCount() 1085 * 1086 * @deprecated Accurate counting is a burden on the runtime and may be removed. 1087 */ 1088 @Deprecated 1089 public static void resetThreadGcInvocationCount() { 1090 VMDebug.resetAllocCount(VMDebug.KIND_THREAD_GC_INVOCATIONS); 1091 } 1092 1093 /** 1094 * Clears all the global and thread-local memory allocation counters. 1095 * @see #startAllocCounting() 1096 * 1097 * @deprecated Accurate counting is a burden on the runtime and may be removed. 1098 */ 1099 @Deprecated 1100 public static void resetAllCounts() { 1101 VMDebug.resetAllocCount(VMDebug.KIND_ALL_COUNTS); 1102 } 1103 1104 /** 1105 * Returns the value of a particular runtime statistic or {@code null} if no 1106 * such runtime statistic exists. 1107 * 1108 * <p>The following table lists the runtime statistics that the runtime supports. 1109 * Note runtime statistics may be added or removed in a future API level.</p> 1110 * 1111 * <table> 1112 * <thead> 1113 * <tr> 1114 * <th>Runtime statistic name</th> 1115 * <th>Meaning</th> 1116 * <th>Example</th> 1117 * <th>Supported (API Levels)</th> 1118 * </tr> 1119 * </thead> 1120 * <tbody> 1121 * <tr> 1122 * <td>art.gc.gc-count</td> 1123 * <td>The number of garbage collection runs.</td> 1124 * <td>{@code 164}</td> 1125 * <td>23</td> 1126 * </tr> 1127 * <tr> 1128 * <td>art.gc.gc-time</td> 1129 * <td>The total duration of garbage collection runs in ms.</td> 1130 * <td>{@code 62364}</td> 1131 * <td>23</td> 1132 * </tr> 1133 * <tr> 1134 * <td>art.gc.bytes-allocated</td> 1135 * <td>The total number of bytes that the application allocated.</td> 1136 * <td>{@code 1463948408}</td> 1137 * <td>23</td> 1138 * </tr> 1139 * <tr> 1140 * <td>art.gc.bytes-freed</td> 1141 * <td>The total number of bytes that garbage collection reclaimed.</td> 1142 * <td>{@code 1313493084}</td> 1143 * <td>23</td> 1144 * </tr> 1145 * <tr> 1146 * <td>art.gc.blocking-gc-count</td> 1147 * <td>The number of blocking garbage collection runs.</td> 1148 * <td>{@code 2}</td> 1149 * <td>23</td> 1150 * </tr> 1151 * <tr> 1152 * <td>art.gc.blocking-gc-time</td> 1153 * <td>The total duration of blocking garbage collection runs in ms.</td> 1154 * <td>{@code 804}</td> 1155 * <td>23</td> 1156 * </tr> 1157 * <tr> 1158 * <td>art.gc.gc-count-rate-histogram</td> 1159 * <td>The histogram of the number of garbage collection runs per 10 seconds.</td> 1160 * <td>{@code 0:34503,1:45350,2:11281,3:8088,4:43,5:8}</td> 1161 * <td>23</td> 1162 * </tr> 1163 * <tr> 1164 * <td>art.gc.blocking-gc-count-rate-histogram</td> 1165 * <td>The histogram of the number of garbage collection runs per 10 seconds.</td> 1166 * <td>{@code 0:99269,1:1,2:1}</td> 1167 * <td>23</td> 1168 * </tr> 1169 * </tbody> 1170 * </table> 1171 * 1172 * @param statName 1173 * the name of the runtime statistic to look up. 1174 * @return the value of the specified runtime statistic or {@code null} if the 1175 * runtime statistic doesn't exist. 1176 */ 1177 public static String getRuntimeStat(String statName) { 1178 return VMDebug.getRuntimeStat(statName); 1179 } 1180 1181 /** 1182 * Returns a map of the names/values of the runtime statistics 1183 * that {@link #getRuntimeStat(String)} supports. 1184 * 1185 * @return a map of the names/values of the supported runtime statistics. 1186 */ 1187 public static Map<String, String> getRuntimeStats() { 1188 return VMDebug.getRuntimeStats(); 1189 } 1190 1191 /** 1192 * Returns the size of the native heap. 1193 * @return The size of the native heap in bytes. 1194 */ 1195 public static native long getNativeHeapSize(); 1196 1197 /** 1198 * Returns the amount of allocated memory in the native heap. 1199 * @return The allocated size in bytes. 1200 */ 1201 public static native long getNativeHeapAllocatedSize(); 1202 1203 /** 1204 * Returns the amount of free memory in the native heap. 1205 * @return The freed size in bytes. 1206 */ 1207 public static native long getNativeHeapFreeSize(); 1208 1209 /** 1210 * Retrieves information about this processes memory usages. This information is broken down by 1211 * how much is in use by dalivk, the native heap, and everything else. 1212 */ 1213 public static native void getMemoryInfo(MemoryInfo memoryInfo); 1214 1215 /** 1216 * Note: currently only works when the requested pid has the same UID 1217 * as the caller. 1218 * @hide 1219 */ 1220 public static native void getMemoryInfo(int pid, MemoryInfo memoryInfo); 1221 1222 /** 1223 * Retrieves the PSS memory used by the process as given by the 1224 * smaps. 1225 */ 1226 public static native long getPss(); 1227 1228 /** 1229 * Retrieves the PSS memory used by the process as given by the 1230 * smaps. Optionally supply a long array of 1 entry to also 1231 * receive the uss of the process, and another array to also 1232 * retrieve the separate memtrack size. @hide 1233 */ 1234 public static native long getPss(int pid, long[] outUss, long[] outMemtrack); 1235 1236 /** @hide */ 1237 public static final int MEMINFO_TOTAL = 0; 1238 /** @hide */ 1239 public static final int MEMINFO_FREE = 1; 1240 /** @hide */ 1241 public static final int MEMINFO_BUFFERS = 2; 1242 /** @hide */ 1243 public static final int MEMINFO_CACHED = 3; 1244 /** @hide */ 1245 public static final int MEMINFO_SHMEM = 4; 1246 /** @hide */ 1247 public static final int MEMINFO_SLAB = 5; 1248 /** @hide */ 1249 public static final int MEMINFO_SWAP_TOTAL = 6; 1250 /** @hide */ 1251 public static final int MEMINFO_SWAP_FREE = 7; 1252 /** @hide */ 1253 public static final int MEMINFO_ZRAM_TOTAL = 8; 1254 /** @hide */ 1255 public static final int MEMINFO_MAPPED = 9; 1256 /** @hide */ 1257 public static final int MEMINFO_VM_ALLOC_USED = 10; 1258 /** @hide */ 1259 public static final int MEMINFO_PAGE_TABLES = 11; 1260 /** @hide */ 1261 public static final int MEMINFO_KERNEL_STACK = 12; 1262 /** @hide */ 1263 public static final int MEMINFO_COUNT = 13; 1264 1265 /** 1266 * Retrieves /proc/meminfo. outSizes is filled with fields 1267 * as defined by MEMINFO_* offsets. 1268 * @hide 1269 */ 1270 public static native void getMemInfo(long[] outSizes); 1271 1272 /** 1273 * Establish an object allocation limit in the current thread. 1274 * This feature was never enabled in release builds. The 1275 * allocation limits feature was removed in Honeycomb. This 1276 * method exists for compatibility and always returns -1 and has 1277 * no effect. 1278 * 1279 * @deprecated This method is now obsolete. 1280 */ 1281 @Deprecated 1282 public static int setAllocationLimit(int limit) { 1283 return -1; 1284 } 1285 1286 /** 1287 * Establish a global object allocation limit. This feature was 1288 * never enabled in release builds. The allocation limits feature 1289 * was removed in Honeycomb. This method exists for compatibility 1290 * and always returns -1 and has no effect. 1291 * 1292 * @deprecated This method is now obsolete. 1293 */ 1294 @Deprecated 1295 public static int setGlobalAllocationLimit(int limit) { 1296 return -1; 1297 } 1298 1299 /** 1300 * Dump a list of all currently loaded class to the log file. 1301 * 1302 * @param flags See constants above. 1303 */ 1304 public static void printLoadedClasses(int flags) { 1305 VMDebug.printLoadedClasses(flags); 1306 } 1307 1308 /** 1309 * Get the number of loaded classes. 1310 * @return the number of loaded classes. 1311 */ 1312 public static int getLoadedClassCount() { 1313 return VMDebug.getLoadedClassCount(); 1314 } 1315 1316 /** 1317 * Dump "hprof" data to the specified file. This may cause a GC. 1318 * 1319 * @param fileName Full pathname of output file (e.g. "/sdcard/dump.hprof"). 1320 * @throws UnsupportedOperationException if the VM was built without 1321 * HPROF support. 1322 * @throws IOException if an error occurs while opening or writing files. 1323 */ 1324 public static void dumpHprofData(String fileName) throws IOException { 1325 VMDebug.dumpHprofData(fileName); 1326 } 1327 1328 /** 1329 * Like dumpHprofData(String), but takes an already-opened 1330 * FileDescriptor to which the trace is written. The file name is also 1331 * supplied simply for logging. Makes a dup of the file descriptor. 1332 * 1333 * Primarily for use by the "am" shell command. 1334 * 1335 * @hide 1336 */ 1337 public static void dumpHprofData(String fileName, FileDescriptor fd) 1338 throws IOException { 1339 VMDebug.dumpHprofData(fileName, fd); 1340 } 1341 1342 /** 1343 * Collect "hprof" and send it to DDMS. This may cause a GC. 1344 * 1345 * @throws UnsupportedOperationException if the VM was built without 1346 * HPROF support. 1347 * @hide 1348 */ 1349 public static void dumpHprofDataDdms() { 1350 VMDebug.dumpHprofDataDdms(); 1351 } 1352 1353 /** 1354 * Writes native heap data to the specified file descriptor. 1355 * 1356 * @hide 1357 */ 1358 public static native void dumpNativeHeap(FileDescriptor fd); 1359 1360 /** 1361 * Returns a count of the extant instances of a class. 1362 * 1363 * @hide 1364 */ 1365 public static long countInstancesOfClass(Class cls) { 1366 return VMDebug.countInstancesOfClass(cls, true); 1367 } 1368 1369 /** 1370 * Returns the number of sent transactions from this process. 1371 * @return The number of sent transactions or -1 if it could not read t. 1372 */ 1373 public static native int getBinderSentTransactions(); 1374 1375 /** 1376 * Returns the number of received transactions from the binder driver. 1377 * @return The number of received transactions or -1 if it could not read the stats. 1378 */ 1379 public static native int getBinderReceivedTransactions(); 1380 1381 /** 1382 * Returns the number of active local Binder objects that exist in the 1383 * current process. 1384 */ 1385 public static final native int getBinderLocalObjectCount(); 1386 1387 /** 1388 * Returns the number of references to remote proxy Binder objects that 1389 * exist in the current process. 1390 */ 1391 public static final native int getBinderProxyObjectCount(); 1392 1393 /** 1394 * Returns the number of death notification links to Binder objects that 1395 * exist in the current process. 1396 */ 1397 public static final native int getBinderDeathObjectCount(); 1398 1399 /** 1400 * Primes the register map cache. 1401 * 1402 * Only works for classes in the bootstrap class loader. Does not 1403 * cause classes to be loaded if they're not already present. 1404 * 1405 * The classAndMethodDesc argument is a concatentation of the VM-internal 1406 * class descriptor, method name, and method descriptor. Examples: 1407 * Landroid/os/Looper;.loop:()V 1408 * Landroid/app/ActivityThread;.main:([Ljava/lang/String;)V 1409 * 1410 * @param classAndMethodDesc the method to prepare 1411 * 1412 * @hide 1413 */ 1414 public static final boolean cacheRegisterMap(String classAndMethodDesc) { 1415 return VMDebug.cacheRegisterMap(classAndMethodDesc); 1416 } 1417 1418 /** 1419 * Dumps the contents of VM reference tables (e.g. JNI locals and 1420 * globals) to the log file. 1421 * 1422 * @hide 1423 */ 1424 public static final void dumpReferenceTables() { 1425 VMDebug.dumpReferenceTables(); 1426 } 1427 1428 /** 1429 * API for gathering and querying instruction counts. 1430 * 1431 * Example usage: 1432 * <pre> 1433 * Debug.InstructionCount icount = new Debug.InstructionCount(); 1434 * icount.resetAndStart(); 1435 * [... do lots of stuff ...] 1436 * if (icount.collect()) { 1437 * System.out.println("Total instructions executed: " 1438 * + icount.globalTotal()); 1439 * System.out.println("Method invocations: " 1440 * + icount.globalMethodInvocations()); 1441 * } 1442 * </pre> 1443 * 1444 * @deprecated Instruction counting is no longer supported. 1445 */ 1446 @Deprecated 1447 public static class InstructionCount { 1448 private static final int NUM_INSTR = 1449 OpcodeInfo.MAXIMUM_PACKED_VALUE + 1; 1450 1451 private int[] mCounts; 1452 1453 public InstructionCount() { 1454 mCounts = new int[NUM_INSTR]; 1455 } 1456 1457 /** 1458 * Reset counters and ensure counts are running. Counts may 1459 * have already been running. 1460 * 1461 * @return true if counting was started 1462 */ 1463 public boolean resetAndStart() { 1464 try { 1465 VMDebug.startInstructionCounting(); 1466 VMDebug.resetInstructionCount(); 1467 } catch (UnsupportedOperationException uoe) { 1468 return false; 1469 } 1470 return true; 1471 } 1472 1473 /** 1474 * Collect instruction counts. May or may not stop the 1475 * counting process. 1476 */ 1477 public boolean collect() { 1478 try { 1479 VMDebug.stopInstructionCounting(); 1480 VMDebug.getInstructionCount(mCounts); 1481 } catch (UnsupportedOperationException uoe) { 1482 return false; 1483 } 1484 return true; 1485 } 1486 1487 /** 1488 * Return the total number of instructions executed globally (i.e. in 1489 * all threads). 1490 */ 1491 public int globalTotal() { 1492 int count = 0; 1493 1494 for (int i = 0; i < NUM_INSTR; i++) { 1495 count += mCounts[i]; 1496 } 1497 1498 return count; 1499 } 1500 1501 /** 1502 * Return the total number of method-invocation instructions 1503 * executed globally. 1504 */ 1505 public int globalMethodInvocations() { 1506 int count = 0; 1507 1508 for (int i = 0; i < NUM_INSTR; i++) { 1509 if (OpcodeInfo.isInvoke(i)) { 1510 count += mCounts[i]; 1511 } 1512 } 1513 1514 return count; 1515 } 1516 } 1517 1518 /** 1519 * A Map of typed debug properties. 1520 */ 1521 private static final TypedProperties debugProperties; 1522 1523 /* 1524 * Load the debug properties from the standard files into debugProperties. 1525 */ 1526 static { 1527 if (false) { 1528 final String TAG = "DebugProperties"; 1529 final String[] files = { "/system/debug.prop", "/debug.prop", "/data/debug.prop" }; 1530 final TypedProperties tp = new TypedProperties(); 1531 1532 // Read the properties from each of the files, if present. 1533 for (String file : files) { 1534 Reader r; 1535 try { 1536 r = new FileReader(file); 1537 } catch (FileNotFoundException ex) { 1538 // It's ok if a file is missing. 1539 continue; 1540 } 1541 1542 try { 1543 tp.load(r); 1544 } catch (Exception ex) { 1545 throw new RuntimeException("Problem loading " + file, ex); 1546 } finally { 1547 try { 1548 r.close(); 1549 } catch (IOException ex) { 1550 // Ignore this error. 1551 } 1552 } 1553 } 1554 1555 debugProperties = tp.isEmpty() ? null : tp; 1556 } else { 1557 debugProperties = null; 1558 } 1559 } 1560 1561 1562 /** 1563 * Returns true if the type of the field matches the specified class. 1564 * Handles the case where the class is, e.g., java.lang.Boolean, but 1565 * the field is of the primitive "boolean" type. Also handles all of 1566 * the java.lang.Number subclasses. 1567 */ 1568 private static boolean fieldTypeMatches(Field field, Class<?> cl) { 1569 Class<?> fieldClass = field.getType(); 1570 if (fieldClass == cl) { 1571 return true; 1572 } 1573 Field primitiveTypeField; 1574 try { 1575 /* All of the classes we care about (Boolean, Integer, etc.) 1576 * have a Class field called "TYPE" that points to the corresponding 1577 * primitive class. 1578 */ 1579 primitiveTypeField = cl.getField("TYPE"); 1580 } catch (NoSuchFieldException ex) { 1581 return false; 1582 } 1583 try { 1584 return fieldClass == (Class<?>) primitiveTypeField.get(null); 1585 } catch (IllegalAccessException ex) { 1586 return false; 1587 } 1588 } 1589 1590 1591 /** 1592 * Looks up the property that corresponds to the field, and sets the field's value 1593 * if the types match. 1594 */ 1595 private static void modifyFieldIfSet(final Field field, final TypedProperties properties, 1596 final String propertyName) { 1597 if (field.getType() == java.lang.String.class) { 1598 int stringInfo = properties.getStringInfo(propertyName); 1599 switch (stringInfo) { 1600 case TypedProperties.STRING_SET: 1601 // Handle as usual below. 1602 break; 1603 case TypedProperties.STRING_NULL: 1604 try { 1605 field.set(null, null); // null object for static fields; null string 1606 } catch (IllegalAccessException ex) { 1607 throw new IllegalArgumentException( 1608 "Cannot set field for " + propertyName, ex); 1609 } 1610 return; 1611 case TypedProperties.STRING_NOT_SET: 1612 return; 1613 case TypedProperties.STRING_TYPE_MISMATCH: 1614 throw new IllegalArgumentException( 1615 "Type of " + propertyName + " " + 1616 " does not match field type (" + field.getType() + ")"); 1617 default: 1618 throw new IllegalStateException( 1619 "Unexpected getStringInfo(" + propertyName + ") return value " + 1620 stringInfo); 1621 } 1622 } 1623 Object value = properties.get(propertyName); 1624 if (value != null) { 1625 if (!fieldTypeMatches(field, value.getClass())) { 1626 throw new IllegalArgumentException( 1627 "Type of " + propertyName + " (" + value.getClass() + ") " + 1628 " does not match field type (" + field.getType() + ")"); 1629 } 1630 try { 1631 field.set(null, value); // null object for static fields 1632 } catch (IllegalAccessException ex) { 1633 throw new IllegalArgumentException( 1634 "Cannot set field for " + propertyName, ex); 1635 } 1636 } 1637 } 1638 1639 1640 /** 1641 * Equivalent to <code>setFieldsOn(cl, false)</code>. 1642 * 1643 * @see #setFieldsOn(Class, boolean) 1644 * 1645 * @hide 1646 */ 1647 public static void setFieldsOn(Class<?> cl) { 1648 setFieldsOn(cl, false); 1649 } 1650 1651 /** 1652 * Reflectively sets static fields of a class based on internal debugging 1653 * properties. This method is a no-op if false is 1654 * false. 1655 * <p> 1656 * <strong>NOTE TO APPLICATION DEVELOPERS</strong>: false will 1657 * always be false in release builds. This API is typically only useful 1658 * for platform developers. 1659 * </p> 1660 * Class setup: define a class whose only fields are non-final, static 1661 * primitive types (except for "char") or Strings. In a static block 1662 * after the field definitions/initializations, pass the class to 1663 * this method, Debug.setFieldsOn(). Example: 1664 * <pre> 1665 * package com.example; 1666 * 1667 * import android.os.Debug; 1668 * 1669 * public class MyDebugVars { 1670 * public static String s = "a string"; 1671 * public static String s2 = "second string"; 1672 * public static String ns = null; 1673 * public static boolean b = false; 1674 * public static int i = 5; 1675 * @Debug.DebugProperty 1676 * public static float f = 0.1f; 1677 * @@Debug.DebugProperty 1678 * public static double d = 0.5d; 1679 * 1680 * // This MUST appear AFTER all fields are defined and initialized! 1681 * static { 1682 * // Sets all the fields 1683 * Debug.setFieldsOn(MyDebugVars.class); 1684 * 1685 * // Sets only the fields annotated with @Debug.DebugProperty 1686 * // Debug.setFieldsOn(MyDebugVars.class, true); 1687 * } 1688 * } 1689 * </pre> 1690 * setFieldsOn() may override the value of any field in the class based 1691 * on internal properties that are fixed at boot time. 1692 * <p> 1693 * These properties are only set during platform debugging, and are not 1694 * meant to be used as a general-purpose properties store. 1695 * 1696 * {@hide} 1697 * 1698 * @param cl The class to (possibly) modify 1699 * @param partial If false, sets all static fields, otherwise, only set 1700 * fields with the {@link android.os.Debug.DebugProperty} 1701 * annotation 1702 * @throws IllegalArgumentException if any fields are final or non-static, 1703 * or if the type of the field does not match the type of 1704 * the internal debugging property value. 1705 */ 1706 public static void setFieldsOn(Class<?> cl, boolean partial) { 1707 if (false) { 1708 if (debugProperties != null) { 1709 /* Only look for fields declared directly by the class, 1710 * so we don't mysteriously change static fields in superclasses. 1711 */ 1712 for (Field field : cl.getDeclaredFields()) { 1713 if (!partial || field.getAnnotation(DebugProperty.class) != null) { 1714 final String propertyName = cl.getName() + "." + field.getName(); 1715 boolean isStatic = Modifier.isStatic(field.getModifiers()); 1716 boolean isFinal = Modifier.isFinal(field.getModifiers()); 1717 1718 if (!isStatic || isFinal) { 1719 throw new IllegalArgumentException(propertyName + 1720 " must be static and non-final"); 1721 } 1722 modifyFieldIfSet(field, debugProperties, propertyName); 1723 } 1724 } 1725 } 1726 } else { 1727 Log.wtf(TAG, 1728 "setFieldsOn(" + (cl == null ? "null" : cl.getName()) + 1729 ") called in non-DEBUG build"); 1730 } 1731 } 1732 1733 /** 1734 * Annotation to put on fields you want to set with 1735 * {@link Debug#setFieldsOn(Class, boolean)}. 1736 * 1737 * @hide 1738 */ 1739 @Target({ ElementType.FIELD }) 1740 @Retention(RetentionPolicy.RUNTIME) 1741 public @interface DebugProperty { 1742 } 1743 1744 /** 1745 * Get a debugging dump of a system service by name. 1746 * 1747 * <p>Most services require the caller to hold android.permission.DUMP. 1748 * 1749 * @param name of the service to dump 1750 * @param fd to write dump output to (usually an output log file) 1751 * @param args to pass to the service's dump method, may be null 1752 * @return true if the service was dumped successfully, false if 1753 * the service could not be found or had an error while dumping 1754 */ 1755 public static boolean dumpService(String name, FileDescriptor fd, String[] args) { 1756 IBinder service = ServiceManager.getService(name); 1757 if (service == null) { 1758 Log.e(TAG, "Can't find service to dump: " + name); 1759 return false; 1760 } 1761 1762 try { 1763 service.dump(fd, args); 1764 return true; 1765 } catch (RemoteException e) { 1766 Log.e(TAG, "Can't dump service: " + name, e); 1767 return false; 1768 } 1769 } 1770 1771 /** 1772 * Have the stack traces of the given native process dumped to the 1773 * specified file. Will be appended to the file. 1774 * @hide 1775 */ 1776 public static native void dumpNativeBacktraceToFile(int pid, String file); 1777 1778 /** 1779 * Return a String describing the calling method and location at a particular stack depth. 1780 * @param callStack the Thread stack 1781 * @param depth the depth of stack to return information for. 1782 * @return the String describing the caller at that depth. 1783 */ 1784 private static String getCaller(StackTraceElement callStack[], int depth) { 1785 // callStack[4] is the caller of the method that called getCallers() 1786 if (4 + depth >= callStack.length) { 1787 return "<bottom of call stack>"; 1788 } 1789 StackTraceElement caller = callStack[4 + depth]; 1790 return caller.getClassName() + "." + caller.getMethodName() + ":" + caller.getLineNumber(); 1791 } 1792 1793 /** 1794 * Return a string consisting of methods and locations at multiple call stack levels. 1795 * @param depth the number of levels to return, starting with the immediate caller. 1796 * @return a string describing the call stack. 1797 * {@hide} 1798 */ 1799 public static String getCallers(final int depth) { 1800 final StackTraceElement[] callStack = Thread.currentThread().getStackTrace(); 1801 StringBuffer sb = new StringBuffer(); 1802 for (int i = 0; i < depth; i++) { 1803 sb.append(getCaller(callStack, i)).append(" "); 1804 } 1805 return sb.toString(); 1806 } 1807 1808 /** 1809 * Return a string consisting of methods and locations at multiple call stack levels. 1810 * @param depth the number of levels to return, starting with the immediate caller. 1811 * @return a string describing the call stack. 1812 * {@hide} 1813 */ 1814 public static String getCallers(final int start, int depth) { 1815 final StackTraceElement[] callStack = Thread.currentThread().getStackTrace(); 1816 StringBuffer sb = new StringBuffer(); 1817 depth += start; 1818 for (int i = start; i < depth; i++) { 1819 sb.append(getCaller(callStack, i)).append(" "); 1820 } 1821 return sb.toString(); 1822 } 1823 1824 /** 1825 * Like {@link #getCallers(int)}, but each location is append to the string 1826 * as a new line with <var>linePrefix</var> in front of it. 1827 * @param depth the number of levels to return, starting with the immediate caller. 1828 * @param linePrefix prefix to put in front of each location. 1829 * @return a string describing the call stack. 1830 * {@hide} 1831 */ 1832 public static String getCallers(final int depth, String linePrefix) { 1833 final StackTraceElement[] callStack = Thread.currentThread().getStackTrace(); 1834 StringBuffer sb = new StringBuffer(); 1835 for (int i = 0; i < depth; i++) { 1836 sb.append(linePrefix).append(getCaller(callStack, i)).append("\n"); 1837 } 1838 return sb.toString(); 1839 } 1840 1841 /** 1842 * @return a String describing the immediate caller of the calling method. 1843 * {@hide} 1844 */ 1845 public static String getCaller() { 1846 return getCaller(Thread.currentThread().getStackTrace(), 0); 1847 } 1848} 1849