FileDocCategorySizeDatePackage
Debug.javaAPI DocAndroid 1.5 API27606Wed May 06 22:41:56 BST 2009android.os

Debug

public final class Debug extends Object
Provides various debugging functions for Android applications, including tracing and allocation counts.

Logging Trace Files

Debug can create log files that give details about an application, such as a call stack and start/stop times for any running methods. See Traceview: A Graphical Log Viewer for information about reading trace files. To start logging trace files, call one of the startMethodTracing() methods. To stop tracing, call {@link #stopMethodTracing()}.

Fields Summary
public static final int
TRACE_COUNT_ALLOCS
Flags for startMethodTracing(). These can be ORed together. TRACE_COUNT_ALLOCS adds the results from startAllocCounting to the trace key file.
public static final int
SHOW_FULL_DETAIL
Flags for printLoadedClasses(). Default behavior is to only show the class name.
public static final int
SHOW_CLASSLOADER
public static final int
SHOW_INITIALIZED
private static volatile boolean
mWaiting
private static final int
MIN_DEBUGGER_IDLE
private static final int
SPIN_DELAY
private static final String
DEFAULT_TRACE_PATH_PREFIX
Default trace file path and file
private static final String
DEFAULT_TRACE_BODY
private static final String
DEFAULT_TRACE_EXTENSION
private static final String
DEFAULT_TRACE_FILE_PATH
private static final String
SYSFS_QEMU_TRACE_STATE
This is the pathname to the sysfs file that enables and disables tracing on the qemu emulator.
Constructors Summary
private Debug()


      
Methods Summary
public static voidchangeDebugPort(int port)
Change the JDWP port.

deprecated
no longer needed or useful

public static voiddumpHprofData(java.lang.String fileName)
Dump "hprof" data to the specified file. This will cause a GC.

param
fileName Full pathname of output file (e.g. "/sdcard/dump.hprof").
throws
UnsupportedOperationException if the VM was built without HPROF support.
throws
IOException if an error occurs while opening or writing files.

        VMDebug.dumpHprofData(fileName);
    
public static voidenableEmulatorTraceOutput()
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();
    
public static final native intgetBinderDeathObjectCount()
Returns the number of death notification links to Binder objects that exist in the current process.

public static final native intgetBinderLocalObjectCount()
Returns the number of active local Binder objects that exist in the current process.

public static final native intgetBinderProxyObjectCount()
Returns the number of references to remote proxy Binder objects that exist in the current process.

public static native intgetBinderReceivedTransactions()
Returns the number of received transactions from the binder driver.

return
The number of received transactions or -1 if it could not read the stats.

public static native intgetBinderSentTransactions()
Returns the number of sent transactions from this process.

return
The number of sent transactions or -1 if it could not read t.

public static intgetGlobalAllocCount()

        return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_OBJECTS);
    
public static intgetGlobalAllocSize()

        return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_BYTES);
    
public static intgetGlobalExternalAllocCount()

        return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_EXT_ALLOCATED_OBJECTS);
    
public static intgetGlobalExternalAllocSize()

        return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_EXT_ALLOCATED_BYTES);
    
public static intgetGlobalExternalFreedCount()

        return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_EXT_FREED_OBJECTS);
    
public static intgetGlobalExternalFreedSize()

        return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_EXT_FREED_BYTES);
    
public static intgetGlobalFreedCount()

        return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_FREED_OBJECTS);
    
public static intgetGlobalFreedSize()

        return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_FREED_BYTES);
    
public static intgetGlobalGcInvocationCount()

        return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_GC_INVOCATIONS);
    
public static intgetLoadedClassCount()
Get the number of loaded classes.

return
the number of loaded classes.

        return VMDebug.getLoadedClassCount();
    
public static native voidgetMemoryInfo(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 longgetNativeHeapAllocatedSize()
Returns the amount of allocated memory in the native heap.

return
The allocated size in bytes.

public static native longgetNativeHeapFreeSize()
Returns the amount of free memory in the native heap.

return
The freed size in bytes.

public static native longgetNativeHeapSize()
Returns the size of the native heap.

return
The size of the native heap in bytes.

public static intgetThreadAllocCount()

        return VMDebug.getAllocCount(VMDebug.KIND_THREAD_ALLOCATED_OBJECTS);
    
public static intgetThreadAllocSize()

        return VMDebug.getAllocCount(VMDebug.KIND_THREAD_ALLOCATED_BYTES);
    
public static intgetThreadExternalAllocCount()

        return VMDebug.getAllocCount(VMDebug.KIND_THREAD_EXT_ALLOCATED_OBJECTS);
    
public static intgetThreadExternalAllocSize()

        return VMDebug.getAllocCount(VMDebug.KIND_THREAD_EXT_ALLOCATED_BYTES);
    
public static intgetThreadGcInvocationCount()

        return VMDebug.getAllocCount(VMDebug.KIND_THREAD_GC_INVOCATIONS);
    
public static booleanisDebuggerConnected()
Determine if a debugger is currently attached.

        return VMDebug.isDebuggerConnected();
    
public static voidprintLoadedClasses(int flags)
Dump a list of all currently loaded class to the log file.

param
flags See constants above.

        VMDebug.printLoadedClasses(flags);
    
public static voidresetAllCounts()

        VMDebug.resetAllocCount(VMDebug.KIND_ALL_COUNTS);
    
public static voidresetGlobalAllocCount()

        VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_OBJECTS);
    
public static voidresetGlobalAllocSize()

        VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_BYTES);
    
public static voidresetGlobalExternalAllocCount()

        VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_EXT_ALLOCATED_OBJECTS);
    
public static voidresetGlobalExternalAllocSize()

        VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_EXT_ALLOCATED_BYTES);
    
public static voidresetGlobalExternalFreedCount()

        VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_EXT_FREED_OBJECTS);
    
public static voidresetGlobalExternalFreedSize()

        VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_EXT_FREED_BYTES);
    
public static voidresetGlobalFreedCount()

        VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_FREED_OBJECTS);
    
public static voidresetGlobalFreedSize()

        VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_FREED_BYTES);
    
public static voidresetGlobalGcInvocationCount()

        VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_GC_INVOCATIONS);
    
public static voidresetThreadAllocCount()

        VMDebug.resetAllocCount(VMDebug.KIND_THREAD_ALLOCATED_OBJECTS);
    
public static voidresetThreadAllocSize()

        VMDebug.resetAllocCount(VMDebug.KIND_THREAD_ALLOCATED_BYTES);
    
public static voidresetThreadExternalAllocCount()

        VMDebug.resetAllocCount(VMDebug.KIND_THREAD_EXT_ALLOCATED_OBJECTS);
    
public static voidresetThreadExternalAllocSize()

        VMDebug.resetAllocCount(VMDebug.KIND_THREAD_EXT_ALLOCATED_BYTES);
    
public static voidresetThreadGcInvocationCount()

        VMDebug.resetAllocCount(VMDebug.KIND_THREAD_GC_INVOCATIONS);
    
public static intsetAllocationLimit(int limit)
Establish an object allocation limit in the current thread. Useful for catching regressions in code that is expected to operate without causing any allocations. Pass in the maximum number of allowed allocations. Use -1 to disable the limit. Returns the previous limit. The preferred way to use this is: int prevLimit = -1; try { prevLimit = Debug.setAllocationLimit(0); ... do stuff that's not expected to allocate memory ... } finally { Debug.setAllocationLimit(prevLimit); } This allows limits to be nested. The try/finally ensures that the limit is reset if something fails. Exceeding the limit causes a dalvik.system.AllocationLimitError to be thrown from a memory allocation call. The limit is reset to -1 when this happens. The feature may be disabled in the VM configuration. If so, this call has no effect, and always returns -1.

        return VMDebug.setAllocationLimit(limit);
    
public static intsetGlobalAllocationLimit(int limit)
Establish a global object allocation limit. This is similar to {@link #setAllocationLimit(int)} but applies to all threads in the VM. It will coexist peacefully with per-thread limits. [ The value of "limit" is currently restricted to 0 (no allocations allowed) or -1 (no global limit). This may be changed in a future release. ]

        if (limit != 0 && limit != -1)
            throw new IllegalArgumentException("limit must be 0 or -1");
        return VMDebug.setGlobalAllocationLimit(limit);
    
public static voidstartAllocCounting()
Count the number and aggregate size of memory allocations between two points. The "start" function resets the counts and enables counting. The "stop" function disables the counting so that the analysis code doesn't cause additional allocations. The "get" function returns the specified value. Counts are kept for the system as a whole 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 voidstartMethodTracing(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.

param
traceName Name for the trace log file to create. If no name argument is given, this value defaults to "/sdcard/dmtrace.trace". If the files already exist, they will be truncated. If the trace file given does not end in ".trace", it will be appended for you.

        startMethodTracing(traceName, 0, 0);
    
public static voidstartMethodTracing(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.

param
traceName Name for the trace log file to create. If no name argument is given, this value defaults to "/sdcard/dmtrace.trace". If the files already exist, they will be truncated. If the trace file given does not end in ".trace", it will be appended for you.
param
bufferSize The maximum amount of trace data we gather. If not given, it defaults to 8MB.

        startMethodTracing(traceName, bufferSize, 0);
    
public static voidstartMethodTracing(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 "native" tracing in the emulator via {@link #startNativeTracing()}.

param
traceName Name for the trace log file to create. If no name argument is given, this value defaults to "/sdcard/dmtrace.trace". If the files already exist, they will be truncated. If the trace file given does not end in ".trace", it will be appended for you.
param
bufferSize The maximum amount of trace data we gather. If not given, it defaults to 8MB.


        String pathName = traceName;
        if (pathName.charAt(0) != '/")
            pathName = DEFAULT_TRACE_PATH_PREFIX + pathName;
        if (!pathName.endsWith(DEFAULT_TRACE_EXTENSION))
            pathName = pathName + DEFAULT_TRACE_EXTENSION;

        VMDebug.startMethodTracing(pathName, bufferSize, flags);
    
public static voidstartMethodTracing()
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);
    
public static voidstartNativeTracing()
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 PrintWriter(new OutputStreamWriter(fos));
            outStream.println("1");
        } catch (Exception e) {
        } finally {
            if (outStream != null)
                outStream.close();
        }

        VMDebug.startEmulatorTracing();
    
public static voidstopAllocCounting()

        VMDebug.stopAllocCounting();
    
public static voidstopMethodTracing()
Stop method tracing.

        VMDebug.stopMethodTracing();
    
public static voidstopNativeTracing()
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 PrintWriter(new OutputStreamWriter(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 longthreadCpuTimeNanos()
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 voidwaitForDebugger()
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 booleanwaitingForDebugger()
Returns "true" if one or more threads is waiting for a debugger to attach.

        return mWaiting;