Methods Summary |
---|
public static final boolean | cacheRegisterMap(java.lang.String classAndMethodDesc)Primes the register map cache.
Only works for classes in the bootstrap class loader. Does not
cause classes to be loaded if they're not already present.
The classAndMethodDesc argument is a concatentation of the VM-internal
class descriptor, method name, and method descriptor. Examples:
Landroid/os/Looper;.loop:()V
Landroid/app/ActivityThread;.main:([Ljava/lang/String;)V
return VMDebug.cacheRegisterMap(classAndMethodDesc);
|
public static void | changeDebugPort(int port)Change the JDWP port.
|
public static long | countInstancesOfClass(java.lang.Class cls)Returns a count of the extant instances of a class.
return VMDebug.countInstancesOfClass(cls, true);
|
public static void | dumpHprofData(java.lang.String fileName)Dump "hprof" data to the specified file. This may cause a GC.
VMDebug.dumpHprofData(fileName);
|
public static void | dumpHprofData(java.lang.String fileName, java.io.FileDescriptor fd)Like dumpHprofData(String), but takes an already-opened
FileDescriptor to which the trace is written. The file name is also
supplied simply for logging. Makes a dup of the file descriptor.
Primarily for use by the "am" shell command.
VMDebug.dumpHprofData(fileName, fd);
|
public static void | dumpHprofDataDdms()Collect "hprof" and send it to DDMS. This may cause a GC.
VMDebug.dumpHprofDataDdms();
|
public static native void | dumpNativeBacktraceToFile(int pid, java.lang.String file)Have the stack traces of the given native process dumped to the
specified file. Will be appended to the file.
|
public static native void | dumpNativeHeap(java.io.FileDescriptor fd)Writes native heap data to the specified file descriptor.
|
public static final void | dumpReferenceTables()Dumps the contents of VM reference tables (e.g. JNI locals and
globals) to the log file.
VMDebug.dumpReferenceTables();
|
public static boolean | dumpService(java.lang.String name, java.io.FileDescriptor fd, java.lang.String[] args)Get a debugging dump of a system service by name.
Most services require the caller to hold android.permission.DUMP.
IBinder service = ServiceManager.getService(name);
if (service == null) {
Log.e(TAG, "Can't find service to dump: " + name);
return false;
}
try {
service.dump(fd, args);
return true;
} catch (RemoteException e) {
Log.e(TAG, "Can't dump service: " + name, e);
return false;
}
|
public static void | enableEmulatorTraceOutput()Enable "emulator traces", in which information about the current
method is made available to the "emulator -trace" feature. There
is no corresponding "disable" call -- this is intended for use by
the framework when tracing should be turned on and left that way, so
that traces captured with F9/F10 will include the necessary data.
This puts the VM into "profile" mode, which has performance
consequences.
To temporarily enable tracing, use {@link #startNativeTracing()}.
VMDebug.startEmulatorTracing();
|
private static boolean | fieldTypeMatches(java.lang.reflect.Field field, java.lang.Class cl)Returns true if the type of the field matches the specified class.
Handles the case where the class is, e.g., java.lang.Boolean, but
the field is of the primitive "boolean" type. Also handles all of
the java.lang.Number subclasses.
if (false) {
final String TAG = "DebugProperties";
final String[] files = { "/system/debug.prop", "/debug.prop", "/data/debug.prop" };
final TypedProperties tp = new TypedProperties();
// Read the properties from each of the files, if present.
for (String file : files) {
Reader r;
try {
r = new FileReader(file);
} catch (FileNotFoundException ex) {
// It's ok if a file is missing.
continue;
}
try {
tp.load(r);
} catch (Exception ex) {
throw new RuntimeException("Problem loading " + file, ex);
} finally {
try {
r.close();
} catch (IOException ex) {
// Ignore this error.
}
}
}
debugProperties = tp.isEmpty() ? null : tp;
} else {
debugProperties = null;
}
Class<?> fieldClass = field.getType();
if (fieldClass == cl) {
return true;
}
Field primitiveTypeField;
try {
/* All of the classes we care about (Boolean, Integer, etc.)
* have a Class field called "TYPE" that points to the corresponding
* primitive class.
*/
primitiveTypeField = cl.getField("TYPE");
} catch (NoSuchFieldException ex) {
return false;
}
try {
return fieldClass == (Class<?>) primitiveTypeField.get(null);
} catch (IllegalAccessException ex) {
return false;
}
|
private static java.lang.String | fixTraceName(java.lang.String traceName)Formats name of trace log file for method tracing.
if (traceName == null)
traceName = DEFAULT_TRACE_FILE_PATH;
if (traceName.charAt(0) != '/")
traceName = DEFAULT_TRACE_PATH_PREFIX + traceName;
if (!traceName.endsWith(DEFAULT_TRACE_EXTENSION))
traceName = traceName + DEFAULT_TRACE_EXTENSION;
return traceName;
|
public static final native int | getBinderDeathObjectCount()Returns the number of death notification links to Binder objects that
exist in the current process.
|
public static final native int | getBinderLocalObjectCount()Returns the number of active local Binder objects that exist in the
current process.
|
public static final native int | getBinderProxyObjectCount()Returns the number of references to remote proxy Binder objects that
exist in the current process.
|
public static native int | getBinderReceivedTransactions()Returns the number of received transactions from the binder driver.
|
public static native int | getBinderSentTransactions()Returns the number of sent transactions from this process.
|
private static java.lang.String | getCaller(java.lang.StackTraceElement[] callStack, int depth)Return a String describing the calling method and location at a particular stack depth.
// callStack[4] is the caller of the method that called getCallers()
if (4 + depth >= callStack.length) {
return "<bottom of call stack>";
}
StackTraceElement caller = callStack[4 + depth];
return caller.getClassName() + "." + caller.getMethodName() + ":" + caller.getLineNumber();
|
public static java.lang.String | getCaller()
return getCaller(Thread.currentThread().getStackTrace(), 0);
|
public static java.lang.String | getCallers(int depth)Return a string consisting of methods and locations at multiple call stack levels.
final StackTraceElement[] callStack = Thread.currentThread().getStackTrace();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < depth; i++) {
sb.append(getCaller(callStack, i)).append(" ");
}
return sb.toString();
|
public static java.lang.String | getCallers(int start, int depth)Return a string consisting of methods and locations at multiple call stack levels.
final StackTraceElement[] callStack = Thread.currentThread().getStackTrace();
StringBuffer sb = new StringBuffer();
depth += start;
for (int i = start; i < depth; i++) {
sb.append(getCaller(callStack, i)).append(" ");
}
return sb.toString();
|
public static java.lang.String | getCallers(int depth, java.lang.String linePrefix)Like {@link #getCallers(int)}, but each location is append to the string
as a new line with linePrefix in front of it.
final StackTraceElement[] callStack = Thread.currentThread().getStackTrace();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < depth; i++) {
sb.append(linePrefix).append(getCaller(callStack, i)).append("\n");
}
return sb.toString();
|
public static int | getGlobalAllocCount()Returns the global count of objects allocated by the runtime between a
{@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_OBJECTS);
|
public static int | getGlobalAllocSize()Returns the global size, in bytes, of objects allocated by the runtime between a
{@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_BYTES);
|
public static int | getGlobalClassInitCount()Returns the number of classes successfully initialized (ie those that executed without
throwing an exception) between a {@link #startAllocCounting() start} and
{@link #stopAllocCounting() stop}.
return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_COUNT);
|
public static int | getGlobalClassInitTime()Returns the time spent successfully initializing classes between a
{@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
/* cumulative elapsed time for class initialization, in usec */
return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_TIME);
|
public static int | getGlobalExternalAllocCount()This method exists for compatibility and always returns 0.
return 0;
|
public static int | getGlobalExternalAllocSize()This method exists for compatibility and always returns 0.
return 0;
|
public static int | getGlobalExternalFreedCount()This method exists for compatibility and always returns 0.
return 0;
|
public static int | getGlobalExternalFreedSize()This method exists for compatibility and has no effect.
return 0;
|
public static int | getGlobalFreedCount()Returns the global count of objects freed by the runtime between a
{@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_FREED_OBJECTS);
|
public static int | getGlobalFreedSize()Returns the global size, in bytes, of objects freed by the runtime between a
{@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_FREED_BYTES);
|
public static int | getGlobalGcInvocationCount()Returns the number of non-concurrent GC invocations between a
{@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_GC_INVOCATIONS);
|
public static int | getLoadedClassCount()Get the number of loaded classes.
return VMDebug.getLoadedClassCount();
|
public static native void | getMemInfo(long[] outSizes)Retrieves /proc/meminfo. outSizes is filled with fields
as defined by MEMINFO_* offsets.
|
public static native void | getMemoryInfo(android.os.Debug$MemoryInfo memoryInfo)Retrieves information about this processes memory usages. This information is broken down by
how much is in use by dalivk, the native heap, and everything else.
|
public static native void | getMemoryInfo(int pid, android.os.Debug$MemoryInfo memoryInfo)Note: currently only works when the requested pid has the same UID
as the caller.
|
public static int | getMethodTracingMode()Determine whether method tracing is currently active and what type is
active.
return VMDebug.getMethodTracingMode();
|
public static native long | getNativeHeapAllocatedSize()Returns the amount of allocated memory in the native heap.
|
public static native long | getNativeHeapFreeSize()Returns the amount of free memory in the native heap.
|
public static native long | getNativeHeapSize()Returns the size of the native heap.
|
public static native long | getPss()Retrieves the PSS memory used by the process as given by the
smaps.
|
public static native long | getPss(int pid, long[] outUss, long[] outMemtrack)Retrieves the PSS memory used by the process as given by the
smaps. Optionally supply a long array of 1 entry to also
receive the uss of the process, and another array to also
retrieve the separate memtrack size. @hide
|
public static int | getThreadAllocCount()Returns the thread-local count of objects allocated by the runtime between a
{@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
return VMDebug.getAllocCount(VMDebug.KIND_THREAD_ALLOCATED_OBJECTS);
|
public static int | getThreadAllocSize()Returns the thread-local size of objects allocated by the runtime between a
{@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
return VMDebug.getAllocCount(VMDebug.KIND_THREAD_ALLOCATED_BYTES);
|
public static int | getThreadExternalAllocCount()This method exists for compatibility and has no effect.
return 0;
|
public static int | getThreadExternalAllocSize()This method exists for compatibility and has no effect.
return 0;
|
public static int | getThreadGcInvocationCount()Returns the number of thread-local non-concurrent GC invocations between a
{@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
return VMDebug.getAllocCount(VMDebug.KIND_THREAD_GC_INVOCATIONS);
|
public static java.lang.String[] | getVmFeatureList()Returns an array of strings that identify VM features. This is
used by DDMS to determine what sorts of operations the VM can
perform.
return VMDebug.getVmFeatureList();
|
public static boolean | isDebuggerConnected()Determine if a debugger is currently attached.
return VMDebug.isDebuggerConnected();
|
private static void | modifyFieldIfSet(java.lang.reflect.Field field, com.android.internal.util.TypedProperties properties, java.lang.String propertyName)Looks up the property that corresponds to the field, and sets the field's value
if the types match.
if (field.getType() == java.lang.String.class) {
int stringInfo = properties.getStringInfo(propertyName);
switch (stringInfo) {
case TypedProperties.STRING_SET:
// Handle as usual below.
break;
case TypedProperties.STRING_NULL:
try {
field.set(null, null); // null object for static fields; null string
} catch (IllegalAccessException ex) {
throw new IllegalArgumentException(
"Cannot set field for " + propertyName, ex);
}
return;
case TypedProperties.STRING_NOT_SET:
return;
case TypedProperties.STRING_TYPE_MISMATCH:
throw new IllegalArgumentException(
"Type of " + propertyName + " " +
" does not match field type (" + field.getType() + ")");
default:
throw new IllegalStateException(
"Unexpected getStringInfo(" + propertyName + ") return value " +
stringInfo);
}
}
Object value = properties.get(propertyName);
if (value != null) {
if (!fieldTypeMatches(field, value.getClass())) {
throw new IllegalArgumentException(
"Type of " + propertyName + " (" + value.getClass() + ") " +
" does not match field type (" + field.getType() + ")");
}
try {
field.set(null, value); // null object for static fields
} catch (IllegalAccessException ex) {
throw new IllegalArgumentException(
"Cannot set field for " + propertyName, ex);
}
}
|
public static void | printLoadedClasses(int flags)Dump a list of all currently loaded class to the log file.
VMDebug.printLoadedClasses(flags);
|
public static void | resetAllCounts()Clears all the global and thread-local memory allocation counters.
VMDebug.resetAllocCount(VMDebug.KIND_ALL_COUNTS);
|
public static void | resetGlobalAllocCount()Clears the global count of objects allocated.
VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_OBJECTS);
|
public static void | resetGlobalAllocSize()Clears the global size of objects allocated.
VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_BYTES);
|
public static void | resetGlobalClassInitCount()Clears the count of classes initialized.
VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_COUNT);
|
public static void | resetGlobalClassInitTime()Clears the count of time spent initializing classes.
VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_TIME);
|
public static void | resetGlobalExternalAllocCount()This method exists for compatibility and has no effect.
|
public static void | resetGlobalExternalAllocSize()This method exists for compatibility and has no effect.
|
public static void | resetGlobalExternalFreedCount()This method exists for compatibility and has no effect.
|
public static void | resetGlobalExternalFreedSize()This method exists for compatibility and has no effect.
|
public static void | resetGlobalFreedCount()Clears the global count of objects freed.
VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_FREED_OBJECTS);
|
public static void | resetGlobalFreedSize()Clears the global size of objects freed.
VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_FREED_BYTES);
|
public static void | resetGlobalGcInvocationCount()Clears the count of non-concurrent GC invocations.
VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_GC_INVOCATIONS);
|
public static void | resetThreadAllocCount()Clears the thread-local count of objects allocated.
VMDebug.resetAllocCount(VMDebug.KIND_THREAD_ALLOCATED_OBJECTS);
|
public static void | resetThreadAllocSize()Clears the thread-local count of objects allocated.
VMDebug.resetAllocCount(VMDebug.KIND_THREAD_ALLOCATED_BYTES);
|
public static void | resetThreadExternalAllocCount()This method exists for compatibility and has no effect.
|
public static void | resetThreadExternalAllocSize()This method exists for compatibility and has no effect.
|
public static void | resetThreadGcInvocationCount()Clears the thread-local count of non-concurrent GC invocations.
VMDebug.resetAllocCount(VMDebug.KIND_THREAD_GC_INVOCATIONS);
|
public static int | setAllocationLimit(int limit)Establish an object allocation limit in the current thread.
This feature was never enabled in release builds. The
allocation limits feature was removed in Honeycomb. This
method exists for compatibility and always returns -1 and has
no effect.
return -1;
|
public static void | setFieldsOn(java.lang.Class cl)Equivalent to setFieldsOn(cl, false) .
setFieldsOn(cl, false);
|
public static void | setFieldsOn(java.lang.Class cl, boolean partial)Reflectively sets static fields of a class based on internal debugging
properties. This method is a no-op if false is
false.
NOTE TO APPLICATION DEVELOPERS: false will
always be false in release builds. This API is typically only useful
for platform developers.
Class setup: define a class whose only fields are non-final, static
primitive types (except for "char") or Strings. In a static block
after the field definitions/initializations, pass the class to
this method, Debug.setFieldsOn(). Example:
package com.example;
import android.os.Debug;
public class MyDebugVars {
public static String s = "a string";
public static String s2 = "second string";
public static String ns = null;
public static boolean b = false;
public static int i = 5;
if (false) {
if (debugProperties != null) {
/* Only look for fields declared directly by the class,
* so we don't mysteriously change static fields in superclasses.
*/
for (Field field : cl.getDeclaredFields()) {
if (!partial || field.getAnnotation(DebugProperty.class) != null) {
final String propertyName = cl.getName() + "." + field.getName();
boolean isStatic = Modifier.isStatic(field.getModifiers());
boolean isFinal = Modifier.isFinal(field.getModifiers());
if (!isStatic || isFinal) {
throw new IllegalArgumentException(propertyName +
" must be static and non-final");
}
modifyFieldIfSet(field, debugProperties, propertyName);
}
}
}
} else {
Log.wtf(TAG,
"setFieldsOn(" + (cl == null ? "null" : cl.getName()) +
") called in non-DEBUG build");
}
|
public static int | setGlobalAllocationLimit(int limit)Establish a global object allocation limit. This feature was
never enabled in release builds. The allocation limits feature
was removed in Honeycomb. This method exists for compatibility
and always returns -1 and has no effect.
return -1;
|
public static void | startAllocCounting()Start counting the number and aggregate size of memory allocations.
The {@link #startAllocCounting() start} method resets the counts and enables counting.
The {@link #stopAllocCounting() stop} method disables the counting so that the analysis
code doesn't cause additional allocations. The various get methods return
the specified value. And the various reset methods reset the specified
count.
Counts are kept for the system as a whole (global) and for each thread.
The per-thread counts for threads other than the current thread
are not cleared by the "reset" or "start" calls.
VMDebug.startAllocCounting();
|
public static void | startMethodTracing()Start method tracing with default log name and buffer size. See Traceview: A Graphical Log Viewer for
information about reading these files. Call stopMethodTracing() to stop
tracing.
VMDebug.startMethodTracing(DEFAULT_TRACE_FILE_PATH, 0, 0, false, 0);
|
public static void | startMethodTracing(java.lang.String traceName)Start method tracing, specifying the trace log file name. The trace
file will be put under "/sdcard" unless an absolute path is given.
See Traceview: A Graphical Log Viewer for
information about reading trace files.
startMethodTracing(traceName, 0, 0);
|
public static void | startMethodTracing(java.lang.String traceName, int bufferSize)Start method tracing, specifying the trace log file name and the
buffer size. The trace files will be put under "/sdcard" unless an
absolute path is given. See Traceview: A Graphical Log Viewer for
information about reading trace files.
startMethodTracing(traceName, bufferSize, 0);
|
public static void | startMethodTracing(java.lang.String traceName, int bufferSize, int flags)Start method tracing, specifying the trace log file name and the
buffer size. The trace files will be put under "/sdcard" unless an
absolute path is given. See Traceview: A Graphical Log Viewer for
information about reading trace files.
When method tracing is enabled, the VM will run more slowly than
usual, so the timings from the trace files should only be considered
in relative terms (e.g. was run #1 faster than run #2). The times
for native methods will not change, so don't try to use this to
compare the performance of interpreted and native implementations of the
same method. As an alternative, consider using sampling-based method
tracing via {@link #startMethodTracingSampling(String, int, int)} or
"native" tracing in the emulator via {@link #startNativeTracing()}.
VMDebug.startMethodTracing(fixTraceName(traceName), bufferSize, flags, false, 0);
|
public static void | startMethodTracing(java.lang.String traceName, java.io.FileDescriptor fd, int bufferSize, int flags)Like startMethodTracing(String, int, int), but taking an already-opened
FileDescriptor in which the trace is written. The file name is also
supplied simply for logging. Makes a dup of the file descriptor.
Not exposed in the SDK unless we are really comfortable with supporting
this and find it would be useful.
VMDebug.startMethodTracing(traceName, fd, bufferSize, flags, false, 0);
|
public static void | startMethodTracingDdms(int bufferSize, int flags, boolean samplingEnabled, int intervalUs)Starts method tracing without a backing file. When stopMethodTracing
is called, the result is sent directly to DDMS. (If DDMS is not
attached when tracing ends, the profiling data will be discarded.)
VMDebug.startMethodTracingDdms(bufferSize, flags, samplingEnabled, intervalUs);
|
public static void | startMethodTracingSampling(java.lang.String traceName, int bufferSize, int intervalUs)Start sampling-based method tracing, specifying the trace log file name,
the buffer size, and the sampling interval. The trace files will be put
under "/sdcard" unless an absolute path is given. See Traceview: A Graphical Log Viewer
for information about reading trace files.
VMDebug.startMethodTracing(fixTraceName(traceName), bufferSize, 0, true, intervalUs);
|
public static void | startNativeTracing()Enable qemu tracing. For this to work requires running everything inside
the qemu emulator; otherwise, this method will have no effect. The trace
file is specified on the command line when the emulator is started. For
example, the following command line
emulator -trace foo
will start running the emulator and create a trace file named "foo". This
method simply enables writing the trace records to the trace file.
The main differences between this and {@link #startMethodTracing()} are
that tracing in the qemu emulator traces every cpu instruction of every
process, including kernel code, so we have more complete information,
including all context switches. We can also get more detailed information
such as cache misses. The sequence of calls is determined by
post-processing the instruction trace. The qemu tracing is also done
without modifying the application or perturbing the timing of calls
because no instrumentation is added to the application being traced.
One limitation of using this method compared to using
{@link #startMethodTracing()} on the real device is that the emulator
does not model all of the real hardware effects such as memory and
bus contention. The emulator also has a simple cache model and cannot
capture all the complexities of a real cache.
// Open the sysfs file for writing and write "1" to it.
PrintWriter outStream = null;
try {
FileOutputStream fos = new FileOutputStream(SYSFS_QEMU_TRACE_STATE);
outStream = new FastPrintWriter(fos);
outStream.println("1");
} catch (Exception e) {
} finally {
if (outStream != null)
outStream.close();
}
VMDebug.startEmulatorTracing();
|
public static void | stopAllocCounting()Stop counting the number and aggregate size of memory allocations.
VMDebug.stopAllocCounting();
|
public static void | stopMethodTracing()Stop method tracing.
VMDebug.stopMethodTracing();
|
public static void | stopNativeTracing()Stop qemu tracing. See {@link #startNativeTracing()} to start tracing.
Tracing can be started and stopped as many times as desired. When
the qemu emulator itself is stopped then the buffered trace records
are flushed and written to the trace file. In fact, it is not necessary
to call this method at all; simply killing qemu is sufficient. But
starting and stopping a trace is useful for examining a specific
region of code.
VMDebug.stopEmulatorTracing();
// Open the sysfs file for writing and write "0" to it.
PrintWriter outStream = null;
try {
FileOutputStream fos = new FileOutputStream(SYSFS_QEMU_TRACE_STATE);
outStream = new FastPrintWriter(fos);
outStream.println("0");
} catch (Exception e) {
// We could print an error message here but we probably want
// to quietly ignore errors if we are not running in the emulator.
} finally {
if (outStream != null)
outStream.close();
}
|
public static long | threadCpuTimeNanos()Get an indication of thread CPU usage. The value returned
indicates the amount of time that the current thread has spent
executing code or waiting for certain types of I/O.
The time is expressed in nanoseconds, and is only meaningful
when compared to the result from an earlier call. Note that
nanosecond resolution does not imply nanosecond accuracy.
On system which don't support this operation, the call returns -1.
return VMDebug.threadCpuTimeNanos();
|
public static void | waitForDebugger()Wait until a debugger attaches. As soon as the debugger attaches,
this returns, so you will need to place a breakpoint after the
waitForDebugger() call if you want to start tracing immediately.
if (!VMDebug.isDebuggingEnabled()) {
//System.out.println("debugging not enabled, not waiting");
return;
}
if (isDebuggerConnected())
return;
// if DDMS is listening, inform them of our plight
System.out.println("Sending WAIT chunk");
byte[] data = new byte[] { 0 }; // 0 == "waiting for debugger"
Chunk waitChunk = new Chunk(ChunkHandler.type("WAIT"), data, 0, 1);
DdmServer.sendChunk(waitChunk);
mWaiting = true;
while (!isDebuggerConnected()) {
try { Thread.sleep(SPIN_DELAY); }
catch (InterruptedException ie) {}
}
mWaiting = false;
System.out.println("Debugger has connected");
/*
* There is no "ready to go" signal from the debugger, and we're
* not allowed to suspend ourselves -- the debugger expects us to
* be running happily, and gets confused if we aren't. We need to
* allow the debugger a chance to set breakpoints before we start
* running again.
*
* Sit and spin until the debugger has been idle for a short while.
*/
while (true) {
long delta = VMDebug.lastDebuggerActivity();
if (delta < 0) {
System.out.println("debugger detached?");
break;
}
if (delta < MIN_DEBUGGER_IDLE) {
System.out.println("waiting for debugger to settle...");
try { Thread.sleep(SPIN_DELAY); }
catch (InterruptedException ie) {}
} else {
System.out.println("debugger has settled (" + delta + ")");
break;
}
}
|
public static boolean | waitingForDebugger()Returns "true" if one or more threads is waiting for a debugger
to attach.
return mWaiting;
|