android debug

Debugging Native Android Platform Code

In this document

  1. debuggerd
  2. Crash dumps
  3. Tombstones
  4. Native Debugging with GDB
    1. Debugging a running app
    2. Debugging a native process as it starts
    3. Debugging processes that crash
    4. Debugging without symbols
  5. Other tools
    1. Valgrind
    2. Systrace

This page contains a summary of useful tools and related commands for debugging, tracing, and profiling native Android platform code. The pages within this section contain detailed information on other debugging tools for use during development of platform-level features.

For example, you may learn how to explore system services with Dumpsys and evaluate network and RAM use. See the subpages for tools and methods not described below.

debuggerd

When a dynamically-linked executable starts, several signal handlers are registered that connect to debuggerd (or debuggerd64) in the event that signal is sent to the process. The debuggerd process dumps registers and unwinds the stack.

It's possible for debuggerd to attach only if nothing else is already attached. This means that using tools like strace or gdb will prevent debuggerd from working. Also, if you call prctl(PR_SET_DUMPABLE, 0) you can prevent debuggerd from attaching. This can be useful if you wish to explicitly opt out of crash reporting.

Here is example output (with timestamps and extraneous information removed):

*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'Android/aosp_flounder/flounder:5.1.51/AOSP/enh08201009:eng/test-keys'
Revision: '0'
ABI: 'arm'
pid: 1656, tid: 1656, name: crasher  >>> crasher <<<
signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
Abort message: 'some_file.c:123: some_function: assertion "false" failed'
    r0 00000000  r1 00000678  r2 00000006  r3 f70b6dc8
    r4 f70b6dd0  r5 f70b6d80  r6 00000002  r7 0000010c
    r8 ffffffed  r9 00000000  sl 00000000  fp ff96ae1c
    ip 00000006  sp ff96ad18  lr f700ced5  pc f700dc98  cpsr 400b0010
backtrace:
    #00 pc 00042c98  /system/lib/libc.so (tgkill+12)
    #01 pc 00041ed1  /system/lib/libc.so (pthread_kill+32)
    #02 pc 0001bb87  /system/lib/libc.so (raise+10)
    #03 pc 00018cad  /system/lib/libc.so (__libc_android_abort+34)
    #04 pc 000168e8  /system/lib/libc.so (abort+4)
    #05 pc 0001a78f  /system/lib/libc.so (__libc_fatal+16)
    #06 pc 00018d35  /system/lib/libc.so (__assert2+20)
    #07 pc 00000f21  /system/xbin/crasher
    #08 pc 00016795  /system/lib/libc.so (__libc_init+44)
    #09 pc 00000abc  /system/xbin/crasher
Tombstone written to: /data/tombstones/tombstone_06

This can be pasted into development/scripts/stack to get a more detailed unwind with line number information (assuming the unstripped binaries can be found).

Some libraries on the system are built with LOCAL_STRIP_MODULE := keep_symbols to provide usable backtraces directly from debuggerd. This makes your library or executable slightly larger, but not nearly as large as an unstripped version.

Note also the last line of debuggerd output --- in addition to dumping a summary to the log, debuggerd writes a full “tombstone” to disk. This contains a lot of extra information that can be helpful in debugging a crash, in particular the stack traces for all the threads in the crashing process (not just the thread that caught the signal) and a full memory map.

Crash dumps

If you don't have a specific crash that you're investigating right now, the platform source includes a tool for testing debuggerd called crasher. If you mm in system/core/debuggerd/ you'll get both a crasher and a crasher64 on your path (the latter allowing you to test 64-bit crashes). Crasher can crash in a large number of interesting ways based on the command line arguments you provide. Use crasher --help to see the currently supported selection.

To introduce the difference pieces in a crash dump, let's work through the example above:

*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***

The line of asterisks with spaces is helpful if you're searching a log for native crashes. The string "*** ***" rarely shows up in logs other than at the beginning of a native crash.

Build fingerprint:
'Android/aosp_flounder/flounder:5.1.51/AOSP/enh08201009:eng/test-keys'

The fingerprint lets you identify exactly which build the crash occurred on. This is exactly the same as the ro.build.fingerprint system property.

Revision: '0'

The revision refers to the hardware rather than the software. This is usually unused but can be useful to help you automatically ignore bugs known to be caused by bad hardware. This is exactly the same as the ro.revision system property.

ABI: 'arm'

The ABI is one of arm, arm64, mips, mips64, x86, or x86-64. This is mostly useful for the stack script mentioned above, so that it knows what toolchain to use.

pid: 1656, tid: 1656, name: crasher >>> crasher <<<

This line identifies the specific thread in the process that crashed. In this case, it was the process' main thread, so the process ID and thread ID match. The first name is the thread name, and the name surrounded by >>> and <<< is the process name. For an app, the process name is typically the fully-qualified package name (such as com.facebook.katana), which is useful when filing bugs or trying to find the app in Google Play. The pid and tid can also be useful in finding the relevant log lines preceding the crash.

signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------

This line tells you which signal (SIGABRT) was received, and more about how it was received (SI_TKILL). The signals reported by debuggerd are SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGSEGV, and SIGTRAP. The signal-specific codes vary based on the specific signal.

Abort message: 'some_file.c:123: some_function: assertion "false" failed'

Not all crashes will have an abort message line, but aborts will. This is automatically gathered from the last line of fatal logcat output for this pid/tid, and in the case of a deliberate abort is likely to give an explanation of why the program killed itself.

r0 00000000 r1 00000678 r2 00000006 r3 f70b6dc8
r4 f70b6dd0 r5 f70b6d80 r6 00000002 r7 0000010c
r8 ffffffed r9 00000000 sl 00000000 fp ff96ae1c
ip 00000006 sp ff96ad18 lr f700ced5 pc f700dc98 cpsr 400b0010

The register dump shows the content of the CPU registers at the time the signal was received. (This section varies wildly between ABIs.) How useful these are will depend on the exact crash.

 

backtrace:
    #00 pc 00042c98 /system/lib/libc.so (tgkill+12)
    #01 pc 00041ed1 /system/lib/libc.so (pthread_kill+32)
    #02 pc 0001bb87 /system/lib/libc.so (raise+10)
    #03 pc 00018cad /system/lib/libc.so (__libc_android_abort+34)
    #04 pc 000168e8 /system/lib/libc.so (abort+4)
    #05 pc 0001a78f /system/lib/libc.so (__libc_fatal+16)
    #06 pc 00018d35 /system/lib/libc.so (__assert2+20)
    #07 pc 00000f21 /system/xbin/crasher
    #08 pc 00016795 /system/lib/libc.so (__libc_init+44)
    #09 pc 00000abc /system/xbin/crasher

The backtrace shows you where in the code we were at the time of crash. The first column is the frame number (matching gdb's style where the deepest frame is 0). The PC values are relative to the location of the shared library rather than absolute addresses. The next column is the name of the mapped region (which is usually a shared library or executable, but might not be for, say, JIT-compiled code). Finally, if symbols are available, the symbol that the PC value corresponds to is shown, along with the offset into that symbol in bytes. You can use this in conjunction with objdump(1) to find the corresponding assembler instruction.

Tombstones

Tombstone written to: /data/tombstones/tombstone_06

This tells you where debuggerd wrote extra information. debuggerd will keep up to 10 tombstones, cycling through the numbers 00 to 09 and overwriting existing tombstones as necessary.

The tombstone contains the same information as the crash dump, plus a few extras. For example, it includes backtraces for all threads (not just the crashing thread), the floating point registers, raw stack dumps, and memory dumps around the addresses in registers. Most usefully it also includes a full memory map (similar to /proc/pid/maps). Here's an annotated example from a 32-bit ARM process crash:

memory map: (fault address prefixed with --->)
--->ab15f000-ab162fff r-x 0 4000 /system/xbin/crasher (BuildId:
b9527db01b5cf8f5402f899f64b9b121)

There are two things to note here. The first is that this line is prefixed with "--->". The maps are most useful when your crash isn't just a null pointer dereference. If the fault address is small, it's probably some variant of a null pointer dereference. Otherwise looking at the maps around the fault address can often give you a clue as to what happened. Some possible issues that can be recognized by looking at the maps include:

  • Reads/writes past the end of a block of memory.
  • Reads/writes before the beginning of a block of memory.
  • Attempts to execute non-code.
  • Running off the end of a stack.
  • Attempts to write to code (as in the example above).

The second thing to note is that executables and shared libraries files will show the BuildId (if present) in Android M and later, so you can see exactly which version of your code crashed. (Platform binaries include a BuildId by default since Android M. NDK r12 and later automatically pass -Wl,--build-id to the linker too.)

 

ab163000-ab163fff r--      3000      1000  /system/xbin/crasher
ab164000-ab164fff rw-         0      1000
f6c80000-f6d7ffff rw-         0    100000  [anon:libc_malloc]

On Android the heap isn't necessarily a single region. Heap regions will be labeled [anon:libc_malloc].

f6d82000-f6da1fff r--         0     20000  /dev/__properties__/u:object_r:logd_prop:s0
f6da2000-f6dc1fff r--         0     20000  /dev/__properties__/u:object_r:default_prop:s0
f6dc2000-f6de1fff r--         0     20000  /dev/__properties__/u:object_r:logd_prop:s0
f6de2000-f6de5fff r-x         0      4000  /system/lib/libnetd_client.so (BuildId: 08020aa06ed48cf9f6971861abf06c9d)
f6de6000-f6de6fff r--      3000      1000  /system/lib/libnetd_client.so
f6de7000-f6de7fff rw-      4000      1000  /system/lib/libnetd_client.so
f6dec000-f6e74fff r-x         0     89000  /system/lib/libc++.so (BuildId: 8f1f2be4b37d7067d366543fafececa2) (load base 0x2000)
f6e75000-f6e75fff ---         0      1000
f6e76000-f6e79fff r--     89000      4000  /system/lib/libc++.so
f6e7a000-f6e7afff rw-     8d000      1000  /system/lib/libc++.so
f6e7b000-f6e7bfff rw-         0      1000  [anon:.bss]
f6e7c000-f6efdfff r-x         0     82000  /system/lib/libc.so (BuildId: d189b369d1aafe11feb7014d411bb9c3)
f6efe000-f6f01fff r--     81000      4000  /system/lib/libc.so
f6f02000-f6f03fff rw-     85000      2000  /system/lib/libc.so
f6f04000-f6f04fff rw-         0      1000  [anon:.bss]
f6f05000-f6f05fff r--         0      1000  [anon:.bss]
f6f06000-f6f0bfff rw-         0      6000  [anon:.bss]
f6f0c000-f6f21fff r-x         0     16000  /system/lib/libcutils.so (BuildId: d6d68a419dadd645ca852cd339f89741)
f6f22000-f6f22fff r--     15000      1000  /system/lib/libcutils.so
f6f23000-f6f23fff rw-     16000      1000  /system/lib/libcutils.so
f6f24000-f6f31fff r-x         0      e000  /system/lib/liblog.so (BuildId: e4d30918d1b1028a1ba23d2ab72536fc)
f6f32000-f6f32fff r--      d000      1000  /system/lib/liblog.so
f6f33000-f6f33fff rw-      e000      1000  /system/lib/liblog.so

Typically a shared library will have three adjacent entries. One will be readable and executable (code), one will be read-only (read-only data), and one will be read-write (mutable data). The first column shows the address ranges for the mapping, the second column the permissions (in the usual Unix ls(1) style), the third column the offset into the file (in hex), the fourth column the size of the region (in hex), and the fifth column the file (or other region name).

f6f34000-f6f53fff r-x         0     20000  /system/lib/libm.so (BuildId: 76ba45dcd9247e60227200976a02c69b)
f6f54000-f6f54fff ---         0      1000
f6f55000-f6f55fff r--     20000      1000  /system/lib/libm.so
f6f56000-f6f56fff rw-     21000      1000  /system/lib/libm.so
f6f58000-f6f58fff rw-         0      1000
f6f59000-f6f78fff r--         0     20000  /dev/__properties__/u:object_r:default_prop:s0
f6f79000-f6f98fff r--         0     20000  /dev/__properties__/properties_serial
f6f99000-f6f99fff rw-         0      1000  [anon:linker_alloc_vector]
f6f9a000-f6f9afff r--         0      1000  [anon:atexit handlers]
f6f9b000-f6fbafff r--         0     20000  /dev/__properties__/properties_serial
f6fbb000-f6fbbfff rw-         0      1000  [anon:linker_alloc_vector]
f6fbc000-f6fbcfff rw-         0      1000  [anon:linker_alloc_small_objects]
f6fbd000-f6fbdfff rw-         0      1000  [anon:linker_alloc_vector]
f6fbe000-f6fbffff rw-         0      2000  [anon:linker_alloc]
f6fc0000-f6fc0fff r--         0      1000  [anon:linker_alloc]
f6fc1000-f6fc1fff rw-         0      1000  [anon:linker_alloc_lob]
f6fc2000-f6fc2fff r--         0      1000  [anon:linker_alloc]
f6fc3000-f6fc3fff rw-         0      1000  [anon:linker_alloc_vector]
f6fc4000-f6fc4fff rw-         0      1000  [anon:linker_alloc_small_objects]
f6fc5000-f6fc5fff rw-         0      1000  [anon:linker_alloc_vector]
f6fc6000-f6fc6fff rw-         0      1000  [anon:linker_alloc_small_objects]
f6fc7000-f6fc7fff rw-         0      1000  [anon:arc4random _rsx structure]
f6fc8000-f6fc8fff rw-         0      1000  [anon:arc4random _rs structure]
f6fc9000-f6fc9fff r--         0      1000  [anon:atexit handlers]
f6fca000-f6fcafff ---         0      1000  [anon:thread signal stack guard page]

Note that since Android 5.0 (Lollipop), the C library names most of its anonymous mapped regions so there are fewer mystery regions.

f6fcb000-f6fccfff rw- 0 2000 [stack:5081]

Regions named [stack:tid] are the stacks for the given threads.

f6fcd000-f702afff r-x         0     5e000  /system/bin/linker (BuildId: 84f1316198deee0591c8ac7f158f28b7)
f702b000-f702cfff r--     5d000      2000  /system/bin/linker
f702d000-f702dfff rw-     5f000      1000  /system/bin/linker
f702e000-f702ffff rw-         0      2000
f7030000-f7030fff r--         0      1000
f7031000-f7032fff rw-         0      2000
ffcd7000-ffcf7fff rw-         0     21000
ffff0000-ffff0fff r-x         0      1000  [vectors]

Whether you see [vector] or [vdso] depends on the architecture. ARM uses [vector], while all other architectures use [vdso].

Native Debugging with GDB

Debugging a running app

To connect to an already-running app or native daemon, use gdbclient.

Current versions of gdbclient just require the process ID (PID). So to debug a process with PID 1234, simply run:

$ gdbclient 1234

The script will set up port forwarding, start the appropriate gdbserver on the device, start the appropriate gdb on the host, configure gdb to find symbols, and connect gdb to the remote gdbserver.

Debugging a native process as it starts

If you want to debug a process as it starts, you’ll need to use gdbserver or gdbserver64 manually, but that’s easy too:

$ adb shell gdbserver :5039 /system/bin/my_test_app
Process my_test_app created; pid = 3460
Listening on port 5039

Identify the app’s PID from the gdbserver output, and then in another window:

$ gdbclient <app pid>

Then enter continue at the gdb prompt.

Note that to debug a 64-bit process, you'll need to use gdbserver64. The error messages from gdb if you made the wrong choice are unhelpful (along the lines of Reply contains invalid hex digit 59).

Debugging processes that crash

If you want debuggerd to suspend crashed processes so you can attach gdb, set the appropriate property:

$ adb shell setprop debug.db.uid 999999                 # <= M
$ adb shell setprop debug.debuggerd.wait_for_gdb true   # > M

At the end of the usual crash output, debuggerd will give you instructions on how to connect gdb using the typical command:

$ gdbclient <pid>

Debugging without symbols

If you don’t have symbols, sometimes gdb will get confused about the instruction set it is disassembling (ARM or Thumb). The instruction set that is chosen as the default when symbol information is missing can be switched between ARM or Thumb like so:

$ set arm fallback-mode arm   # or 'thumb'

Other tools

Valgrind

The following steps show you how to use Valgrind on Android. This tool suite contains a number of tools including Memcheck for detecting memory-related errors in C and C++.

  1. To build Valgrind, run:
    $ mmma -j6 external/valgrind
  2. Set up the temporary directory:
    $ adb shell mkdir /data/local/tmp
    $ adb shell chmod 777 /data/local/tmp
  3. Run the system server with Valgrind:
    $ adb shell setprop wrap.system_server "logwrapper valgrind"
    $ adb shell stop && adb shell start
  4. For debug symbols, push unstripped libraries to /data/local/symbols:
    $ adb shell mkdir /data/local/symbols
    $ adb push $OUT/symbols /data/local/symbols
  5. To use Valgrind during boot up, edit out/target/product/XXXX/root/init.rc and change:
    service example /system/bin/foo --arg1 --arg2
    to:
    service example /system/bin/logwrapper /system/bin/valgrind /system/bin/foo --arg1 --arg2
    To see the effects, you need to create a boot.img and reflash the device.

 

 

https://developer.android.com/studio/profile/systrace-commandline.html

Systrace

See Systrace on developer.android.com for deriving execution times of applications and other Android system processes.

 

Systrace

The Systrace tool helps analyze the performance of your application by capturing and displaying execution times of your applications processes and other Android system processes. The tool combines data from the Android kernel such as the CPU scheduler, disk activity, and application threads to generate an HTML report that shows an overall picture of an Android device’s system processes for a given period of time.

The Systrace tool is particularly useful in diagnosing display problems where an application is slow to draw or stutters while displaying motion or animation. For more information on how to use Systrace, see Analyzing UI Performance with Systrace.

Requirements

In order to run Systrace, you must have Android SDK Tools 20 or later installed. You must also have Python installed and included in your development computer's execution path. In order to generate a trace, you must connect a device running Android 4.1 (API Level 16) or higher to your development system using a USB debugging connection.

The Systrace tool can be run either from one of the Android SDK's graphical user interface tools, or from the command line. The following sections describe how to run the tool using either of these methods.

User Interface

The Systrace tool can be run from the Android Device Monitor.

To run the Systrace capture user interface:

Using Android Studio

Using Device Monitor

Command Line Usage

The Systrace tool has different command line options for devices running Android 4.3 (API level 18) and higher versus devices running Android 4.2 (API level 17) and lower. The following sections describe the different command line options for each version.

The general syntax for running Systrace from the command line is as follows.

$ python systrace.py [options] [category1] [category2] ... [categoryN]

See the sections below for example Systrace sessions.

Android 4.3 and higher options

When you use Systrace on devices running Android 4.3 and higher, you can omit trace category tags to get the defaults, or you may manually specify tags for inclusion. Here is an example execution run that sets trace tags and generates a trace from a connected device.

$ cd android-sdk/platform-tools/systrace
$ python systrace.py --time=10 -o mynewtrace.html sched gfx view wm

Tip: If you want to see the names of tasks in the trace output, you must include the sched category in your command parameters.

The table below lists the Systrace command line options for devices running Android 4.3 (API level 18) and higher.

OptionDescription
-h, --helpShow the help message.
-o <FILE>Write the HTML trace report to the specified file.
-t N, --time=NTrace activity for N seconds. The default value is 5 seconds.
-b N, --buf-size=NUse a trace buffer size of N kilobytes. This option lets you limit the total size of the data collected during a trace.
-k <KFUNCS>
--ktrace=<KFUNCS>
Trace the activity of specific kernel functions, specified in a comma-separated list.
-l, --list-categoriesList the available tracing category tags.

Note: Trace categories can differ across devices.

Tip: If you want to see the names of tasks in the trace output, you must include the sched category in your command parameters.

-a <APP_NAME>
--app=<APP_NAME>
Enable tracing for applications, specified as a comma-separated list of package names. The apps must contain tracing instrumentation calls from the Trace class. For more information, see Analyzing UI Performance with Systrace.
--from-file=<FROM_FILE>Create the interactive Systrace report from a file, instead of running a live trace.
-e <DEVICE_SERIAL>
--serial=<DEVICE_SERIAL>
Conduct the trace on a specific connected device, identified by its device serial number.

Android 4.2 and lower options

Using Systrace on the command line with devices running Android 4.2 and lower is typically a two-step process. You must first set the trace tags you want to capture and then run the trace. Here is an example execution run that sets trace tags and generates a trace from a connected device.

$ cd android-sdk/platform-tools/systrace
$ python systrace.py --set-tags gfx,view,wm
$ adb shell stop
$ adb shell start
$ python systrace.py --disk --time=10 -o mynewtrace.html

The table below lists the Systrace command line options for devices running Android 4.2 (API level 17) and lower.

OptionDescription
-h, --helpShow the help message.
-o <FILE>Write the HTML trace report to the specified file.
-t N, --time=NTrace activity for N seconds. The default value is 5 seconds.
-b N, --buf-size=NUse a trace buffer size of N kilobytes. This option lets you limit the total size of the data collected during a trace.
-d, --diskTrace disk input and output activity. This option requires root access on the device.
-f, --cpu-freqTrace CPU frequency changes. Only changes to the CPU frequency are logged, so the initial frequency of the CPU when tracing starts is not shown.
-i, --cpu-idleTrace CPU idle events.
-l, --cpu-loadTrace CPU load. This value is a percentage determined by the interactive CPU frequency governor.
-s, --no-cpu-schedPrevent tracing of the CPU scheduler. This option allows for longer trace times by reducing the rate of data flowing into the trace buffer.
-u, --bus-utilizationTrace the bus utilization levels. This option requires root access on the device.
-w, --workqueueTrace kernel work queues. This option requires root access on the device.
--set-tags=<TAGS>Set the enabled trace tags in a comma separated list. The available tags are:
  • gfx - Graphics
  • input - Input
  • view - View
  • webview - WebView
  • wm - Window Manager
  • am - Activity Manager
  • sync - Synchronization Manager
  • audio - Audio
  • video - Video
  • camera - Camera

Note: When setting trace tags from the command line, you must stop and restart the framework ($ adb shell stop; adb shell start) for the tag tracing changes to take effect.

You can set the trace tags for Systrace on your Android 4.2 and lower device by navigating to Settings > Developer options > Monitoring > Enable traces.

Trace Viewing Shortcuts

The table below lists the keyboard shortcuts that are available while viewing a Systrace trace HTML report.

KeyDescription
wZoom into the trace timeline.
sZoom out of the trace timeline.
aPan left on the trace timeline.
dPan right on the trace timeline.
eCenter the trace timeline on the current mouse location.
gShow grid at the start of the currently selected task.
Shift+gShow grid at the end of the currently selected task.
Right ArrowSelect the next event on the currently selected timeline.
Left ArrowSelect the previous event on the currently selected timeline.

 

 

 

 

 

AddressSanitizer

In this document

  1. Purpose
  2. Building with Clang
  3. Building executables with AddressSanitizer
  4. Building shared libraries with AddressSanitizer
  5. Better stack traces
  6. Symbolization
  7. AddressSanitizer in the apps
  8. Using the wrap property
  9. SANITIZE_TARGET
  10. Supporting documentation

Purpose

AddressSanitizer (ASan) is a fast compiler-based tool for detecting memory bugs in native code. It is comparable to Valgrind (Memcheck tool), but, unlike it, ASan:

  • + detects overflows on stack and global objects
  • - does not detect uninitialized reads and memory leaks
  • + is much faster (two-three times slowdown compared to Valgrind’s 20-100x)
  • + has less memory overhead

This document describes how to build and run parts of the Android platform with AddressSanitizer. If you are looking to build a standalone (i.e. SDK/NDK) application with AddressSanitizer, see the AddressSanitizerOnAndroid public project site instead.

AddressSanitizer consists of a compiler (external/clang) and a runtime library (external/compiler-rt/lib/asan).

Note: Use the current master branch to gain access to the SANITIZE_TARGET feature and the ability to build the entire Android platform with AddressSanitizer at once. Otherwise, you are limited to using LOCAL_SANITIZE.

Building with Clang

As a first step to building an ASan-instrumented binary, make sure that your code builds with Clang. This is done by adding LOCAL_CLANG:=true to the build rules. Clang may find bugs in your code that GCC missed.

Building executables with AddressSanitizer

Add LOCAL_SANITIZE:=address to the build rule of the executable. This requires: LOCAL_CLANG:=true

LOCAL_CLANG:=true
LOCAL_SANITIZE:=address

When a bug is detected, ASan prints a verbose report both to the standard output and to logcat and then crashes the process.

Building shared libraries with AddressSanitizer

Due to the way ASan works, a library built with ASan cannot be used by an executable that's built without ASan.

Note: In runtime situations where an ASan library is loaded into an incorrect process, you will see unresolved symbol messages starting with _asan or _sanitizer.

To sanitize a shared library that is used in multiple executables, not all of which are built with ASan, you'll need two copies of the library. The recommended way to do this is to add the following to Android.mk for the module in question:

LOCAL_CLANG:=true
LOCAL_SANITIZE:=address
LOCAL_MODULE_RELATIVE_PATH := asan

This puts the library in /system/lib/asan instead of /system/lib. Then, run your executable with: LD_LIBRARY_PATH=/system/lib/asan

For system daemons, add the following to the appropriate section of /init.rc or /init.$device$.rc.

setenv LD_LIBRARY_PATH /system/lib/asan

Warning: The LOCAL_MODULE_RELATIVE_PATH setting moves your library to /system/lib/asan, meaning that clobbering and rebuilding from scratch will result in the library missing from /system/lib, and probably an unbootable image. That's an unfortunate limitation of the current build system. Don't clobber; do make -j $N and adb sync.

Verify the process is using libraries from /system/lib/asan when present by reading /proc/$PID/maps. If it's not, you may need to disable SELinux, like so:

$ adb root
$ adb shell setenforce 0
# restart the process with adb shell kill $PID
# if it is a system service, or may be adb shell stop; adb shell start.

Better stack traces

AddressSanitizer uses a fast, frame-pointer-based unwinder to record a stack trace for every memory allocation and deallocation event in the program. Most of Android is built without frame pointers. As a result, you will often get only one or two meaningful frames. To fix this, either rebuild the library with ASan (recommended!), or with:

LOCAL_CFLAGS:=-fno-omit-frame-pointer
LOCAL_ARM_MODE:=arm

Or set ASAN_OPTIONS=fast_unwind_on_malloc=0 in the process environment. The latter can be very CPU-intensive, depending on the load.

Symbolization

Initially, ASan reports contain references to offsets in binaries and shared libraries. There are two ways to obtain source file and line information:

  • Ensure llvm-symbolizer binary is present in /system/bin. Llvm-symbolizer is built from sources in: third_party/llvm/tools/llvm-symbolizer
  • Filter the report through the external/compiler-rt/lib/asan/scripts/symbolize.py script.

The second approach can provide more data (i.e. file:line locations) because of the availability of symbolized libraries on the host.

AddressSanitizer in the apps

AddressSanitizer cannot see into Java code, but it can detect bugs in the JNI libraries. For that, you'll need to build the executable with ASan, which in this case is /system/bin/app_process(32|64). This will enable ASan in all apps on the device at the same time, which is a bit stressful, but nothing that a 2GB RAM device cannot handle.

Add the usual LOCAL_CLANG:=true, LOCAL_SANITIZE:=address to the app_process build rule in frameworks/base/cmds/app_process. Ignore the app_process__asan target in the same file for now (if it is still there at the time you read this). Edit the Zygote record in system/core/rootdir/init.zygote(32|64).rc to add the following lines:

setenv LD_LIBRARY_PATH /system/lib/asan:/system/lib
setenv ASAN_OPTIONS
allow_user_segv_handler=true

Build, adb sync, fastboot flash boot, reboot.

Using the wrap property

The approach in the previous section puts AddressSanitizer into every application in the system (actually, into every descendant of the Zygote process). It is possible to run only one (or several) applications with ASan, trading some memory overhead for slower application startup.

This can be done by starting your app with the “wrap.” property, the same one that’s used to run apps under Valgrind. The following example runs the Gmail app under ASan:

$ adb root
$ adb shell setenforce 0  # disable SELinux
$ adb shell setprop wrap.com.google.android.gm "asanwrapper"

In this context, asanwrapper rewrites /system/bin/app_process to /system/bin/asan/app_process, which is built with AddressSanitizer. It also adds /system/lib/asan at the start of the dynamic library search path. This way ASan-instrumented libraries from /system/lib/asan are preferred to normal libraries in /system/lib when running with asanwrapper.

Again, if a bug is found, the app will crash, and the report will be printed to the log.

SANITIZE_TARGET

The master branch has support for building the entire Android platform with AddressSanitizer at once.

Run the following commands in the same build tree.

$ make -j42
$ make USE_CLANG_PLATFORM_BUILD:=true SANITIZE_TARGET=address -j42

In this mode, userdata.img contains extra libraries and must be flashed to the device as well. Use the following command line:

$ fastboot flash userdata && fastboot flashall

At the moment of this writing, hammerhead-userdebug and shamu-userdebug boot to the UI in this mode.

This works by building two sets of shared libraries: normal in /system/lib (the first make invocation), ASan-instrumented in /data/lib (the second make invocation). Executables from the second build overwrite the ones from the first build. ASan-instrumented executables get a different library search path that includes /data/lib before /system/lib through the use of "/system/bin/linker_asan" in PT_INTERP.

The build system clobbers intermediate object directories when the $SANITIZE_TARGET value has changed. This forces a rebuild of all targets while preserving installed binaries under /system/lib.

Some targets cannot be built with ASan:

  • Statically linked executables.
  • LOCAL_CLANG:=false targets
  • LOCAL_SANITIZE:=undefined; will not be ASan'd for SANITIZE_TARGET=address

Executables like these are skipped in the SANITIZE_TARGET build, and the version from the first make invocation is left in /system/bin.

Libraries like this are simply built without ASan. They can contain some ASan code anyway from the static libraries they depend upon.

Supporting documentation

AddressSanitizerOnAndroid public project site

AddressSanitizer and Chromium

Other Google Sanitizers

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2=======================================================

If you run adb shell dumpsys, you’ll get diagnostic output for all system services, which is usually more than you want. For more manageable output, specify the service you would like to examine.

For example, the following command:

$ adb shell dumpsys input

provides system data for input components such as touchscreens or built-in keyboards.

List of system services

For a complete list of system services that you can use with dumpsys, try the following command:

$ adb shell dumpsys -l
Currently running services:
  DockObserver
  SurfaceFlinger
  accessibility
  account
  activity
  alarm
  android.security.keystore
  appops
  appwidget
  assetatlas
  audio
  backup
  battery
  batteryproperties
  batterystats
  bluetooth_manager
  clipboard
  connectivity
  consumer_ir
  content
  country_detector
  cpuinfo
  dbinfo
...

Dumpsys command-line options

Command-line options are different for different services. Here are a few common ones:

  • For many services, you can append -h to see the help text.
  • For some services, you can append -c to view the data in a machine-friendly format.

Understanding diagnostic output

For details on some of the most commonly used dumpsys services, see the following articles:

 

 

 

 

 

 

3========================================================

Malloc debug

See Malloc Debug and Native Memory Tracking using libc Callbacks for a thorough description of the debugging options available for native memory issues.

Dalvik Debug Monitor Server

You can also use the Dalvik Debug Monitor Server (DDMS) to obtain a graphical view of Malloc Debug output.

To use DDMS, first turn on its native memory UI:

  1. Open ~/.android/ddms.cfg
  2. Add the line: native=true

Upon relaunching DDMS and selecting a process, you can switch to the new native allocation tab and populate it with a list of allocations. This is especially useful for debugging memory leaks.

 

 

Malloc Debug

Malloc debug is a method of debugging native memory problems. It can help detect memory corruption, memory leaks, and use after free issues.

This documentation describes how to enable this feature on Android N or later versions of the Android OS.

The documentation for malloc debug on older versions of Android is here.

In order to enable malloc debug, you must be able to set special system properties using the setprop command from the shell. This requires the ability to run as root on the device.

When malloc debug is enabled, it works by adding a shim layer that replaces the normal allocation calls. The replaced calls are:

  • malloc
  • free
  • calloc
  • realloc
  • posix_memalign
  • memalign
  • malloc_usable_size

On 32 bit systems, these two deprecated functions are also replaced:

  • pvalloc
  • valloc

Any errors detected by the library are reported in the log.

Controlling Malloc Debug Behavior

Malloc debug is controlled by individual options. Each option can be enabled individually, or in a group of other options. Every single option can be combined with every other option.

Option Descriptions

front_guard[=SIZE_BYTES]

Enables a small buffer placed before the allocated data. This is an attempt to find memory corruption occuring to a region before the original allocation. On first allocation, this front guard is written with a specific pattern (0xaa). When the allocation is freed, the guard is checked to verify it has not been modified. If any part of the front guard is modified, an error will be reported in the log indicating what bytes changed.

If the backtrace option is also enabled, then any error message will include the backtrace of the allocation site.

If SIZE_BYTES is present, it indicates the number of bytes in the guard. The default is 32 bytes, the max bytes is 16384. SIZE_BYTES will be padded so that it is a multiple of 8 bytes on 32 bit systems and 16 bytes on 64 bit systems to make sure that the allocation returned is aligned properly.

This option adds a special header to all allocations that contains the guard and information about the original allocation.

Example error:

04-10 12:00:45.621  7412  7412 E malloc_debug: +++ ALLOCATION 0x12345678 SIZE 100 HAS A CORRUPTED FRONT GUARD
04-10 12:00:45.622  7412  7412 E malloc_debug:   allocation[-32] = 0x00 (expected 0xaa)
04-10 12:00:45.622  7412  7412 E malloc_debug:   allocation[-15] = 0x02 (expected 0xaa)

rear_guard[=SIZE_BYTES]

Enables a small buffer placed after the allocated data. This is an attempt to find memory corruption occuring to a region after the original allocation. On first allocation, this rear guard is written with a specific pattern (0xbb). When the allocation is freed, the guard is checked to verify it has not been modified. If any part of the rear guard is modified, an error will be reported in the log indicating what bytes changed.

If SIZE_BYTES is present, it indicates the number of bytes in the guard. The default is 32 bytes, the max bytes is 16384.

This option adds a special header to all allocations that contains information about the original allocation.

Example error:

04-10 12:00:45.621  7412  7412 E malloc_debug: +++ ALLOCATION 0x12345678 SIZE 100 HAS A CORRUPTED REAR GUARD
04-10 12:00:45.622  7412  7412 E malloc_debug:   allocation[130] = 0xbf (expected 0xbb)
04-10 12:00:45.622  7412  7412 E malloc_debug:   allocation[131] = 0x00 (expected 0xbb)

guard[=SIZE_BYTES]

Enables both a front guard and a rear guard on all allocations.

If SIZE_BYTES is present, it indicates the number of bytes in both guards. The default is 32 bytes, the max bytes is 16384.

backtrace[=MAX_FRAMES]

Enable capturing the backtrace of each allocation site. This option will slow down allocations by an order of magnitude. If the system runs too slowly with this option enabled, decreasing the maximum number of frames captured will speed the allocations up.

Note that any backtrace frames that occur within the malloc backtrace library itself are not recorded.

If MAX_FRAMES is present, it indicates the maximum number of frames to capture in a backtrace. The default is 16 frames, the maximumum value this can be set to is 256.

This option adds a special header to all allocations that contains the backtrace and information about the original allocation.

backtrace_enable_on_signal[=MAX_FRAMES]

Enable capturing the backtrace of each allocation site. If the backtrace capture is toggled when the process receives the signal SIGRTMAX - 19 (which is 45 on most Android devices). When this option is used alone, backtrace capture starts out disabled until the signal is received. If both this option and the backtrace option are set, then backtrace capture is enabled until the signal is received.

If MAX_FRAMES is present, it indicates the maximum number of frames to capture in a backtrace. The default is 16 frames, the maximumum value this can be set to is 256.

This option adds a special header to all allocations that contains the backtrace and information about the original allocation.

fill_on_alloc[=MAX_FILLED_BYTES]

Any allocation routine, other than calloc, will result in the allocation being filled with the value 0xeb. When doing a realloc to a larger size, the bytes above the original usable size will be set to 0xeb.

If MAX_FILLED_BYTES is present, it will only fill up to the specified number of bytes in the allocation. The default is to fill the entire allocation.

fill_on_free[=MAX_FILLED_BYTES]

When an allocation is freed, fill it with 0xef.

If MAX_FILLED_BYTES is present, it will only fill up to the specified number of bytes in the allocation. The default is to fill the entire allocation.

fill[=MAX_FILLED_BYTES]

This enables both the fill_on_alloc option and the fill_on_free option.

If MAX_FILLED_BYTES is present, it will only fill up to the specified number of bytes in the allocation. The default is to fill the entire allocation.

expand_alloc[=EXPAND_BYTES]

Add an extra amount to allocate for every allocation.

If XX is present, it is the number of bytes to expand the allocation by. The default is 16 bytes, the max bytes is 16384.

free_track[=ALLOCATION_COUNT]

When a pointer is freed, do not free the memory right away, but add it to a list of freed allocations. In addition to being added to the list, the entire allocation is filled with the value 0xef, and the backtrace at the time of the free is recorded. The backtrace recording is completely separate from the backtrace option, and happens automatically if this option is enabled. By default, a maximum of 16 frames will be recorded, but this value can be changed using the free_track_backtrace_num_frames option. It can also be completely disabled by setting the option to zero. See the full description of this option below.

When the list is full, an allocation is removed from the list and is checked to make sure that none of the contents have been modified since being placed on the list. When the program terminates, all of the allocations left on the list are verified.

If ALLOCATION_COUNT is present, it indicates the total number of allocations in the list. The default is to record 100 freed allocations, the max allocations to record is 16384.

This option adds a special header to all allocations that contains information about the original allocation.

Example error:

04-15 12:00:31.304  7412  7412 E malloc_debug: +++ ALLOCATION 0x12345678 USED AFTER FREE
04-15 12:00:31.305  7412  7412 E malloc_debug:   allocation[20] = 0xaf (expected 0xef)
04-15 12:00:31.305  7412  7412 E malloc_debug:   allocation[99] = 0x12 (expected 0xef)
04-15 12:00:31.305  7412  7412 E malloc_debug: Backtrace at time of free:
04-15 12:00:31.305  7412  7412 E malloc_debug:           #00  pc 00029310  /system/lib/libc.so
04-15 12:00:31.305  7412  7412 E malloc_debug:           #01  pc 00021438  /system/lib/libc.so (newlocale+160)
04-15 12:00:31.305  7412  7412 E malloc_debug:           #02  pc 000a9e38  /system/lib/libc++.so
04-15 12:00:31.305  7412  7412 E malloc_debug:           #03  pc 000a28a8  /system/lib/libc++.so

In addition, there is another type of error message that can occur if an allocation has a special header applied, and the header is corrupted before the verification occurs. This is the error message that will be found in the log:

04-15 12:00:31.604  7412  7412 E malloc_debug: +++ ALLOCATION 0x12345678 HAS CORRUPTED HEADER TAG 0x1cc7dc00 AFTER FREE

free_track_backtrace_num_frames[=MAX_FRAMES]

This option only has meaning if free_track is set. It indicates how many backtrace frames to capture when an allocation is freed.

If MAX_FRAMES is present, it indicates the number of frames to capture. If the value is set to zero, then no backtrace will be captured when the allocation is freed. The default is to record 16 frames, the max number of frames to to record is 256.

leak_track

Track all live allocations. When the program terminates, all of the live allocations will be dumped to the log. If the backtrace option was enabled, then the log will include the backtrace of the leaked allocations. This option is not useful when enabled globally because a lot of programs do not free everything before the program terminates.

This option adds a special header to all allocations that contains information about the original allocation.

Example leak error found in the log:

04-15 12:35:33.304  7412  7412 E malloc_debug: +++ APP leaked block of size 100 at 0x2be3b0b0 (leak 1 of 2)
04-15 12:35:33.304  7412  7412 E malloc_debug: Backtrace at time of allocation:
04-15 12:35:33.305  7412  7412 E malloc_debug:           #00  pc 00029310  /system/lib/libc.so
04-15 12:35:33.305  7412  7412 E malloc_debug:           #01  pc 00021438  /system/lib/libc.so (newlocale+160)
04-15 12:35:33.305  7412  7412 E malloc_debug:           #02  pc 000a9e38  /system/lib/libc++.so
04-15 12:35:33.305  7412  7412 E malloc_debug:           #03  pc 000a28a8  /system/lib/libc++.so
04-15 12:35:33.305  7412  7412 E malloc_debug: +++ APP leaked block of size 24 at 0x7be32380 (leak 2 of 2)
04-15 12:35:33.305  7412  7412 E malloc_debug: Backtrace at time of allocation:
04-15 12:35:33.305  7412  7412 E malloc_debug:           #00  pc 00029310  /system/lib/libc.so
04-15 12:35:33.305  7412  7412 E malloc_debug:           #01  pc 00021438  /system/lib/libc.so (newlocale+160)
04-15 12:35:33.305  7412  7412 E malloc_debug:           #02  pc 000a9e38  /system/lib/libc++.so
04-15 12:35:33.305  7412  7412 E malloc_debug:           #03  pc 000a28a8  /system/lib/libc++.so

record_allocs[=TOTAL_ENTRIES]

Keep track of every allocation/free made on every thread and dump them to a file when the signal SIGRTMAX - 18 (which is 46 on most Android devices) is received.

If TOTAL_ENTRIES is set, then it indicates the total number of allocation/free records that can be retained. If the number of records reaches the TOTAL_ENTRIES value, then any further allocations/frees are not recorded. The default value is 8,000,000 and the maximum value this can be set to is 50,000,000.

Once the signal is received, and the current records are written to the file, all current records are deleted. Any allocations/frees occuring while the data is being dumped to the file are ignored.

NOTE: This option is not available until the O release of Android.

The allocation data is written in a human readable format. Every line begins with the THREAD_ID returned by gettid(), which is the thread that is making the allocation/free. If a new thread is created, no special line is added to the file. However, when a thread completes, a special entry is added to the file indicating this.

The thread complete line is:

THREAD_ID: thread_done 0x0

Example:

187: thread_done 0x0

Below is how each type of allocation/free call ends up in the file dump.

pointer = malloc(size)

THREAD_ID: malloc pointer size

Example:

186: malloc 0xb6038060 20

free(pointer)

THREAD_ID: free pointer

Example:

186: free 0xb6038060

pointer = calloc(nmemb, size)

THREAD_ID: calloc pointer nmemb size

Example:

186: calloc 0xb609f080 32 4

new_pointer = realloc(old_pointer, size)

THREAD_ID: realloc new_pointer old_pointer size

Example:

186: realloc 0xb609f080 0xb603e9a0 12

pointer = memalign(alignment, size)

THREAD_ID: memalign pointer alignment size

posix_memalign(&pointer, alignment, size)

THREAD_ID: memalign pointer alignment size

Example:

186: memalign 0x85423660 16 104

pointer = valloc(size)

THREAD_ID: memalign pointer 4096 size

Example:

186: memalign 0x85423660 4096 112

pointer = pvalloc(size)

THREAD_ID: memalign pointer 4096 SIZE_ROUNDED_UP_TO_4096

Example:

186: memalign 0x85423660 4096 8192

record_allocs_file[=FILE_NAME]

This option only has meaning if record_allocs is set. It indicates the file where the recorded allocations will be found.

If FILE_NAME is set, then it indicates where the record allocation data will be placed.

NOTE: This option is not available until the O release of Android.

Additional Errors

There are a few other error messages that might appear in the log.

Use After Free

04-15 12:00:31.304  7412  7412 E malloc_debug: +++ ALLOCATION 0x12345678 USED AFTER FREE (free)
04-15 12:00:31.305  7412  7412 E malloc_debug: Backtrace of original free:
04-15 12:00:31.305  7412  7412 E malloc_debug:           #00  pc 00029310  /system/lib/libc.so
04-15 12:00:31.305  7412  7412 E malloc_debug:           #01  pc 00021438  /system/lib/libc.so (newlocale+160)
04-15 12:00:31.305  7412  7412 E malloc_debug:           #02  pc 000a9e38  /system/lib/libc++.so
04-15 12:00:31.305  7412  7412 E malloc_debug:           #03  pc 000a28a8  /system/lib/libc++.so
04-15 12:00:31.305  7412  7412 E malloc_debug: Backtrace at time of failure:
04-15 12:00:31.305  7412  7412 E malloc_debug:           #00  pc 00029310  /system/lib/libc.so
04-15 12:00:31.305  7412  7412 E malloc_debug:           #01  pc 00021438  /system/lib/libc.so (newlocale+160)
04-15 12:00:31.305  7412  7412 E malloc_debug:           #02  pc 000a9e38  /system/lib/libc++.so
04-15 12:00:31.305  7412  7412 E malloc_debug:           #03  pc 000a28a8  /system/lib/libc++.so

This indicates that code is attempting to free an already freed pointer. The name in parenthesis indicates that the application called the function free with the bad pointer.

For example, this message:

04-15 12:00:31.304  7412  7412 E malloc_debug: +++ ALLOCATION 0x12345678 USED AFTER FREE (realloc)

Would indicate that the application called the realloc function with an already freed pointer.

Invalid Tag

04-15 12:00:31.304  7412  7412 E malloc_debug: +++ ALLOCATION 0x12345678 HAS INVALID TAG 1ee7d000 (malloc_usable_size)
04-15 12:00:31.305  7412  7412 E malloc_debug: Backtrace at time of failure:
04-15 12:00:31.305  7412  7412 E malloc_debug:           #00  pc 00029310  /system/lib/libc.so
04-15 12:00:31.305  7412  7412 E malloc_debug:           #01  pc 00021438  /system/lib/libc.so (newlocale+160)
04-15 12:00:31.305  7412  7412 E malloc_debug:           #02  pc 000a9e38  /system/lib/libc++.so
04-15 12:00:31.305  7412  7412 E malloc_debug:           #03  pc 000a28a8  /system/lib/libc++.so

This indicates that a function (malloc_usable_size) was called with a pointer that is either not allocated memory, or that the memory of the pointer has been corrupted.

As with the other error message, the function in parenthesis is the function that was called with the bad pointer.

Examples

Enable backtrace tracking of all allocation for all processes:

adb shell stop
adb shell setprop libc.debug.malloc.options backtrace
adb shell start

Enable backtrace tracking for a specific process (ls):

adb shell setprop libc.debug.malloc.options backtrace
adb shell setprop libc.debug.malloc.program ls
adb shell ls

Enable backtrace tracking for the zygote and zygote based processes:

adb shell stop
adb shell setprop libc.debug.malloc.program app_process
adb shell setprop libc.debug.malloc.options backtrace
adb shell start

Enable multiple options (backtrace and guards):

adb shell stop
adb shell setprop libc.debug.malloc.options "\"backtrace guards\""
adb shell start

Enable malloc debug when multiple processes have the same name. This method can be used to enable malloc debug for only a very specific process if multiple processes have the same name.

Note: The double quotes in the adb shell command are necessary. Otherwise, the setprop command will fail since the backtrace guards options will look like two arguments instead of one.

adb shell
# setprop libc.debug.malloc.env_enabled
# setprop libc.debug.malloc.options backtrace
# export LIBC_DEBUG_MALLOC_ENABLE 1
# ls

Enable malloc debug and dump the native allocation with backtraces to a file. This only works for zygote based java processes.

adb shell stop
adb shell setprop libc.debug.malloc.options backtrace
adb shell start
adb shell am dumpheap -n <PID_TO_DUMP> /data/local/tmp/heap.txt

It is possible to use the backtrace_enable_on_signal option as well, but it must be enabled through the signal before the file will contain any data.

 

 

Native Memory Tracking using libc Callbacks

Malloc debug can be used to get information on all of the live allocations in a process. The libc library in Android exports two calls that can be used to gather this data from a process. This tracking can be enabled using either the backtrace option or the backtrace_enabled_on_signal option.

The function to gather the data:

extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overall_size, size_t* info_size, size_t* total_memory, size_t* backtrace_size);

info is set to a buffer allocated by the call that contains all of the allocation information. overall_size is set to the total size of the buffer returned. If this info_size value is zero, then there are no allocation being tracked. total_memory is set to the sum of all allocation sizes that are live at the point of the function call. This does not include the memory allocated by the malloc debug library itself. backtrace_size is set to the maximum number of backtrace entries that are present for each allocation.

In order to free the buffer allocated by the function, call:

extern "C" void free_malloc_leak_info(uint8_t* info);

Format of info Buffer

size_t size_of_original_allocation
size_t num_backtrace_frames
uintptr_t pc1
uintptr_t pc2
uintptr_t pc3
.
.
.

The number of uintptr_t values is determined by the value backtrace_size as returned by the original call to get_malloc_leak_info. This value is not variable, it is the same for all the returned data. The value num_backtrace_frames contains the real number of frames found. The extra frames are set to zero. Each uintptr_t is a pc of the callstack. The calls from within the malloc debug library are automatically removed.

For 32 bit systems, size_t and uintptr_t are both 4 byte values.

For 64 bit systems, size_t and uintptr_t are both 8 byte values.

The total number of these structures returned in info is overall_size divided by info_size.

Note, the size value in each allocation data structure will have bit 31 set if this allocation was created in a process forked from the Zygote process. This helps to distinguish between native allocations created by the application.

 

Viewing Network Usage Data

Using the command adb shell dumpsys netstats detail provides network usage statistics collected since the device booted up.

Input

To view network usage statistics, run the following command:

$ adb shell dumpsys netstats detail

Output

The set of information reported varies depending on the version of Android but consists of several sections:

  • Active interfaces
  • Active UID interfaces
  • Dev statistics
  • Xt statistics
  • UID statistics (sometimes also called "Detailed UID statistics")
  • UID tag statistics

Active interfaces/Active UID interfaces

Here is sample output for the active interfaces and active UID interfaces sections:

Active interfaces:
  iface=wlan0 ident=[{type=WIFI, subType=COMBINED, networkId="GoogleGuest"}]
Active UID interfaces:
  iface=wlan0 ident=[{type=WIFI, subType=COMBINED, networkId="GoogleGuest"}]

This shows network statistics for the whole device. In most cases, the information in these two section is the same.

Dev statistics/Xt statistics

Here is sample output for the Dev statistics section:

Dev stats:
  Pending bytes: 170775
  Complete history:
  ident=[[type=MOBILE_HIPRI, subType=COMBINED, subscriberId=311111...]] uid=-1 set=ALL tag=0x0
    NetworkStatsHistory: bucketDuration=3600000
      bucketStart=1406138400000 activeTime=3603995 rxBytes=19467 rxPackets=53 txBytes=7500 txPackets=61 operations=0
      bucketStart=1406142000000 activeTime=20730 rxBytes=25403 rxPackets=66 txBytes=9140 txPackets=74 operations=0
      bucketStart=1406145600000 activeTime=29161 rxBytes=9263 rxPackets=37 txBytes=5180 txPackets=38 operations=0
      bucketStart=1406149200000 activeTime=9054 rxBytes=12387 rxPackets=31 txBytes=4052 txPackets=35 operations=0
  ident=[[type=WIFI, subType=COMBINED, networkId="MySSID"]] uid=-1 set=ALL tag=0x0
    NetworkStatsHistory: bucketDuration=3600000
      bucketStart=1406138400000 activeTime=4811082 rxBytes=335913292 rxPackets=265144 txBytes=9729261 txPackets=117220 operations=0
      bucketStart=1406142000000 activeTime=3513477 rxBytes=1193606876 rxPackets=956855 txBytes=29450792 txPackets=306634 operations=0
      bucketStart=1406145600000 activeTime=3297986 rxBytes=729381849 rxPackets=586396 txBytes=24247211 txPackets=237438 operations=0
      bucketStart=1406149200000 activeTime=3580941 rxBytes=57168575 rxPackets=51610 txBytes=5291167 txPackets=29260 operations=0
  ident=[[type=WIFI, subType=COMBINED, networkId="MySecondSSID"]] uid=-1 set=ALL tag=0x0
    NetworkStatsHistory: bucketDuration=3600000

UID stats

UID stats:
  Pending bytes: 744
  Complete history:
  ident=[[type=MOBILE_SUPL, subType=COMBINED, subscriberId=311111...], [type=MOBILE, subType=COMBINED, subscriberId=311111...]] uid=10007 set=DEFAULT tag=0x0
    NetworkStatsHistory: bucketDuration=7200000
      bucketStart=1406167200000 activeTime=7200000 rxBytes=4666 rxPackets=7 txBytes=1597 txPackets=10 operations=0
  ident=[[type=WIFI, subType=COMBINED, networkId="MySSID"]] uid=10007 set=DEFAULT tag=0x0
    NetworkStatsHistory: bucketDuration=7200000
      bucketStart=1406138400000 activeTime=7200000 rxBytes=17086802 rxPackets=15387 txBytes=1214969 txPackets=8036 operations=28
      bucketStart=1406145600000 activeTime=7200000 rxBytes=2396424 rxPackets=2946 txBytes=464372 txPackets=2609 operations=70
      bucketStart=1406152800000 activeTime=7200000 rxBytes=200907 rxPackets=606 txBytes=187418 txPackets=739 operations=0
      bucketStart=1406160000000 activeTime=7200000 rxBytes=826017 rxPackets=1126 txBytes=267342 txPackets=1175 operations=35

Interpreting the results

To find the UID for your application, you can run this command: adb shell dumpsys package <your package name>. Then look for the line labeled userId.

In our example, suppose we are trying to find network usage for our app “com.example.myapp”. We would run the following command:

$ adb shell dumpsys package com.example.myapp | grep userId

    userId=10007 gids=[3003, 1028, 1015]

Looking at the dump above, we look for lines that have uid=10007. Two such lines exist, the first indicating a mobile connection, and the second a Wi-Fi connection. Underneath each line, the number of bytes and packets sent and received can be seen, bucketed into two-hour windows.

A bit more explanation:

  • set=DEFAULT indicates foreground network usage, while set=BACKGROUND indicates background usage. set=ALL implies both.
  • tag=0x0 indicates the socket tag associated with the traffic.
  • rxBytes and rxPackets represent received bytes and received packets in the corresponding time interval.
  • txBytes and txPackets represent sent (transmitted) bytes and sent packets in the corresponding time interval.

 

Viewing RAM Usage Data (procstats)

In this document

  1. Input
  2. Output

The procstats tool is used to analyze application memory usage over time (versus at a particular snapshot in time, like meminfo). Its state dump displays statistics about every application’s runtime, proportional set size (PSS) and unique set size (USS).

Input

To get application memory usage stats for the last three hours, in human-readable form, run the following command:

$ adb shell dumpsys procstats --hours 3

Output

As can be seen in the example below, percentages display what percentage of time the application was running, while the numbers following show PSS and USS as minPSS-avgPSS-maxPSS/minUSS-avgUSS-maxUSS over samples.

AGGREGATED OVER LAST 3 HOURS:
  * com.android.systemui / u0a20 / v22:
           TOTAL: 100% (109MB-126MB-159MB/108MB-125MB-157MB over 18)
      Persistent: 100% (109MB-126MB-159MB/108MB-125MB-157MB over 18)
  * com.android.nfc / 1027 / v22:
           TOTAL: 100% (17MB-17MB-17MB/16MB-16MB-16MB over 18)
      Persistent: 100% (17MB-17MB-17MB/16MB-16MB-16MB over 18)
  * android.process.acore / u0a4 / v22:
           TOTAL: 100% (14MB-15MB-15MB/14MB-14MB-14MB over 20)
          Imp Fg: 100% (14MB-15MB-15MB/14MB-14MB-14MB over 20)
  * com.google.android.inputmethod.latin / u0a56 / v21483:
           TOTAL: 100% (57MB-59MB-59MB/56MB-58MB-58MB over 19)
          Imp Fg: 100% (57MB-59MB-59MB/56MB-58MB-58MB over 19)
  * com.redbend.vdmc / 1001 / v1:
           TOTAL: 100% (9.5MB-9.6MB-9.7MB/8.8MB-8.9MB-9.0MB over 18)
      Persistent: 100% (9.5MB-9.6MB-9.7MB/8.8MB-8.9MB-9.0MB over 18)
  * com.android.phone / 1001 / v22:
           TOTAL: 100% (19MB-22MB-27MB/18MB-21MB-26MB over 18)
      Persistent: 100% (19MB-22MB-27MB/18MB-21MB-26MB over 18)
  * com.google.android.gms.persistent / u0a8 / v7319438:
           TOTAL: 100% (32MB-35MB-40MB/30MB-33MB-37MB over 19)
          Imp Fg: 100% (32MB-35MB-40MB/30MB-33MB-37MB over 19)
  * com.android.bluetooth / 1002 / v22:
           TOTAL: 100% (9.3MB-9.7MB-10MB/8.5MB-8.9MB-9.2MB over 19)
          Imp Fg: 100% (9.3MB-9.7MB-10MB/8.5MB-8.9MB-9.2MB over 19)
  * com.google.android.googlequicksearchbox:interactor / u0a22 / v300404573:
           TOTAL: 100% (3.4MB-3.5MB-3.6MB/2.8MB-2.8MB-2.8MB over 19)
          Imp Fg: 100% (3.4MB-3.5MB-3.6MB/2.8MB-2.8MB-2.8MB over 19)
  * com.google.process.gapps / u0a8 / v7306438:
           TOTAL: 100% (23MB-24MB-28MB/21MB-22MB-26MB over 19)
          Imp Fg: 100% (23MB-24MB-28MB/21MB-22MB-26MB over 19)
  * com.vito.lux / u0a84 / v237:
           TOTAL: 100% (32MB-48MB-83MB/31MB-47MB-82MB over 134)
          Imp Fg: 100% (32MB-48MB-83MB/31MB-47MB-82MB over 134)
         Service: 0.05%
  * system / 1000 / v22:
           TOTAL: 100% (79MB-85MB-102MB/78MB-83MB-100MB over 18)
      Persistent: 100% (79MB-85MB-102MB/78MB-83MB-100MB over 18)
  * com.rhapsody / u0a83 / v125:
           TOTAL: 100% (7.9MB-12MB-19MB/6.9MB-11MB-17MB over 15)
         Service: 100% (7.9MB-12MB-19MB/6.9MB-11MB-17MB over 15)
      Service Rs: 0.04%
  * com.qualcomm.qcrilmsgtunnel / 1001 / v22:
           TOTAL: 100% (2.5MB-2.6MB-2.7MB/1.7MB-1.8MB-1.9MB over 15)
         Service: 100% (2.5MB-2.6MB-2.7MB/1.7MB-1.8MB-1.9MB over 15)
      Service Rs: 0.13%
  * com.amazon.kindle / u0a82 / v1143472216:
           TOTAL: 100% (44MB-54MB-77MB/43MB-52MB-74MB over 17)
         Service: 100% (44MB-54MB-77MB/43MB-52MB-74MB over 17)
      Service Rs: 0.04%
  * com.outplaylab.VideoDiet2 / u0a93 / v21:
           TOTAL: 100% (2.8MB-3.1MB-4.0MB/2.0MB-2.2MB-3.0MB over 15)
         Service: 100% (2.8MB-3.1MB-4.0MB/2.0MB-2.2MB-3.0MB over 15)
      Service Rs: 0.03%
  * android.process.media / u0a6 / v800:
           TOTAL: 99% (4.6MB-5.9MB-8.1MB/3.4MB-4.7MB-6.7MB over 25)
          Imp Fg: 0.02%
         Service: 99% (4.6MB-5.9MB-8.1MB/3.4MB-4.7MB-6.7MB over 25)
      Service Rs: 0.02%
        (Cached): 0.94%
  * kr.sira.sound / u0a108 / v41:
           TOTAL: 77% (117MB-191MB-219MB/111MB-187MB-213MB over 68)
             Top: 77% (117MB-191MB-219MB/111MB-187MB-213MB over 68)
      (Last Act): 18% (58MB-127MB-161MB/53MB-123MB-158MB over 3)
        (Cached): 0.06%
  * com.google.android.gms / u0a8 / v7319438:
           TOTAL: 37% (41MB-45MB-57MB/38MB-42MB-53MB over 23)
             Top: 13% (41MB-46MB-57MB/39MB-42MB-53MB over 16)
          Imp Fg: 13% (41MB-44MB-47MB/39MB-41MB-44MB over 5)
          Imp Bg: 0.38%
         Service: 11% (42MB-42MB-42MB/38MB-38MB-38MB over 2)
        Receiver: 0.03%
      (Last Act): 2.0% (38MB-38MB-38MB/36MB-36MB-36MB over 1)
        (Cached): 61% (39MB-40MB-43MB/37MB-37MB-40MB over 28)
  * com.google.android.googlequicksearchbox / u0a22 / v300404573:
           TOTAL: 22% (129MB-153MB-162MB/125MB-149MB-156MB over 20)
             Top: 22% (129MB-153MB-162MB/125MB-149MB-156MB over 20)
          Imp Bg: 0.04%
        Receiver: 0.01%
          (Home): 78% (75MB-84MB-122MB/74MB-82MB-117MB over 12)
  * com.google.android.apps.thehub / u0a102 / v12:
           TOTAL: 21% (6.4MB-7.6MB-8.7MB/4.8MB-6.0MB-7.2MB over 2)
         Service: 21% (6.4MB-7.6MB-8.7MB/4.8MB-6.0MB-7.2MB over 2)
  * com.google.android.talk / u0a54 / v22314462:
           TOTAL: 9.3%
             Top: 0.04%
         Service: 9.3%
        Receiver: 0.01%
      (Last Act): 3.9% (69MB-70MB-71MB/67MB-68MB-69MB over 6)
        (Cached): 87% (42MB-53MB-77MB/40MB-51MB-74MB over 137)
  * com.google.android.apps.plus / u0a67 / v413836278:
           TOTAL: 8.2% (9.6MB-12MB-18MB/8.1MB-11MB-16MB over 3)
          Imp Bg: 0.10%
         Service: 8.0% (9.6MB-12MB-18MB/8.1MB-11MB-16MB over 3)
        Receiver: 0.05%
        (Cached): 59% (7.8MB-19MB-33MB/6.8MB-18MB-31MB over 22)
  * com.android.providers.calendar / u0a2 / v22:
           TOTAL: 3.5% (7.3MB-7.7MB-8.0MB/5.9MB-6.5MB-6.9MB over 10)
          Imp Bg: 0.32%
         Service: 3.2% (7.3MB-7.7MB-8.0MB/5.9MB-6.5MB-6.9MB over 10)
        Receiver: 0.01%
        (Cached): 69% (4.7MB-6.6MB-7.8MB/3.5MB-5.5MB-6.7MB over 23)
  * com.amazon.mShop.android / u0a104 / v5030102:
           TOTAL: 2.7% (25MB-40MB-47MB/24MB-37MB-43MB over 6)
         Service: 2.6% (25MB-40MB-47MB/24MB-37MB-43MB over 6)
        Receiver: 0.15%
        (Cached): 97% (25MB-33MB-48MB/24MB-31MB-44MB over 46)
  * com.google.android.gm / u0a70 / v51001620:
           TOTAL: 2.2% (209MB-209MB-209MB/203MB-203MB-203MB over 1)
             Top: 0.48% (209MB-209MB-209MB/203MB-203MB-203MB over 1)
          Imp Bg: 0.70%
         Service: 1.0%
        Receiver: 0.01%
      (Last Act): 0.02%
        (Cached): 94% (25MB-67MB-116MB/23MB-63MB-109MB over 61)
  * com.google.android.googlequicksearchbox:search / u0a22 / v300404573:
           TOTAL: 2.1% (66MB-66MB-66MB/63MB-63MB-63MB over 1)
             Top: 1.4% (66MB-66MB-66MB/63MB-63MB-63MB over 1)
          Imp Fg: 0.01%
         Service: 0.66%
        Receiver: 0.02%
        (Cached): 98% (52MB-59MB-79MB/50MB-56MB-77MB over 56)
  * com.google.android.calendar / u0a31 / v2015030452:
           TOTAL: 1.4%
          Imp Bg: 0.33%
         Service: 1.1%
        Receiver: 0.02%
        (Cached): 80% (7.4MB-12MB-17MB/5.8MB-9.8MB-14MB over 18)
  * com.android.vending / u0a16 / v80341100:
           TOTAL: 1.3% (88MB-154MB-220MB/85MB-151MB-217MB over 2)
             Top: 1.3% (88MB-154MB-220MB/85MB-151MB-217MB over 2)
         Service: 0.06%
        Receiver: 0.02%
      (Last Act): 4.4% (46MB-68MB-89MB/45MB-66MB-87MB over 2)
        (Cached): 11% (15MB-74MB-133MB/13MB-72MB-131MB over 2)
  * com.google.android.apps.photos / u0a65 / v5616:
           TOTAL: 0.94%
         Service: 0.90%
        Receiver: 0.04%
        (Cached): 80% (9.2MB-12MB-17MB/7.5MB-11MB-15MB over 20)
  * com.amazon.avod.thirdpartyclient / u0a107 / v451210:
           TOTAL: 0.52%
         Service: 0.49%
        Receiver: 0.03%
        (Cached): 97% (14MB-24MB-34MB/13MB-22MB-31MB over 40)
  * com.google.android.gms.wearable / u0a8 / v7319438:
           TOTAL: 0.51%
          Imp Fg: 0.47%
         Service: 0.04%
        (Cached): 65% (4.7MB-6.5MB-8.2MB/3.6MB-4.2MB-5.4MB over 10)
  * com.amazon.mShop.android.shopping / u0a103 / v5040011:
           TOTAL: 0.50%
         Service: 0.37%
        Receiver: 0.13%
        (Cached): 77% (13MB-17MB-21MB/11MB-15MB-19MB over 15)
  * com.google.android.gms:car / u0a8 / v7319438:
           TOTAL: 0.49% (7.1MB-7.1MB-7.1MB/4.3MB-4.3MB-4.3MB over 1)
             Top: 0.05%
          Imp Fg: 0.39% (7.1MB-7.1MB-7.1MB/4.3MB-4.3MB-4.3MB over 1)
         Service: 0.05%
        (Cached): 0.60% (6.6MB-6.6MB-6.6MB/3.6MB-3.6MB-3.6MB over 1)
  * com.amazon.mp3 / u0a92 / v4033010:
           TOTAL: 0.46%
         Service: 0.43%
        Receiver: 0.03%
        (Cached): 84% (12MB-16MB-23MB/9.7MB-14MB-21MB over 25)
  * com.android.chrome:privileged_process1 / u0a34 / v2272096:
           TOTAL: 0.43%
         Service: 0.04%
      Service Rs: 0.39%
        (Cached): 100% (2.9MB-4.0MB-4.9MB/1.7MB-2.9MB-3.9MB over 18)
  * com.google.android.dialer / u0a10 / v20100:
           TOTAL: 0.39% (93MB-93MB-93MB/89MB-89MB-89MB over 1)
             Top: 0.23% (93MB-93MB-93MB/89MB-89MB-89MB over 1)
          Imp Fg: 0.16%
        (Cached): 16% (5.0MB-31MB-57MB/4.1MB-29MB-54MB over 2)
  * com.google.android.apps.maps / u0a58 / v906101124:
           TOTAL: 0.38%
         Service: 0.33%
        Receiver: 0.05%
        (Cached): 69% (8.7MB-15MB-18MB/7.2MB-14MB-17MB over 8)
  * com.google.android.youtube / u0a80 / v101451214:
           TOTAL: 0.26%
         Service: 0.26%
        (Cached): 36% (15MB-22MB-29MB/13MB-19MB-27MB over 5)
  * com.google.android.apps.fitness / u0a45 / v2015109100:
           TOTAL: 0.26%
         Service: 0.23%
        Receiver: 0.02%
        (Cached): 82% (3.9MB-6.4MB-9.2MB/2.8MB-5.3MB-7.9MB over 19)
  * com.google.android.apps.enterprise.dmagent / u0a37 / v630:
           TOTAL: 0.06%
         Service: 0.06%
        Receiver: 0.01%
        (Cached): 2.2% (6.5MB-7.4MB-8.2MB/4.8MB-5.8MB-6.8MB over 2)
  * com.audible.application / u0a95 / v3068:
           TOTAL: 0.06%
        Receiver: 0.06%
        (Cached): 34% (14MB-16MB-19MB/11MB-14MB-17MB over 7)
  * com.android.defcontainer / u0a5 / v22:
           TOTAL: 0.06%
          Imp Fg: 0.06%
        (Cached): 0.12%
  * com.google.android.music:main / u0a60 / v1847:
           TOTAL: 0.04%
             Top: 0.01%
         Service: 0.02%
        Receiver: 0.01%
        (Cached): 9.8% (10MB-12MB-14MB/8.3MB-9.6MB-11MB over 2)
  * com.google.android.apps.magazines / u0a61 / v2015040100:
           TOTAL: 0.03%
             Top: 0.02%
        Receiver: 0.01%
        (Cached): 8.7% (12MB-14MB-16MB/9.7MB-11MB-13MB over 2)
  * com.google.android.videos / u0a77 / v37191:
           TOTAL: 0.03%
          Imp Fg: 0.01%
         Service: 0.02%
        (Cached): 1.3% (11MB-12MB-13MB/9.1MB-10MB-12MB over 2)
  * com.google.android.apps.books / u0a28 / v30336:
           TOTAL: 0.03%
          Imp Fg: 0.01%
         Service: 0.02%
        (Cached): 1.3% (7.9MB-9.6MB-11MB/6.3MB-8.0MB-9.7MB over 2)
  * com.google.android.keep / u0a71 / v3115:
           TOTAL: 0.02%
         Service: 0.01%
        Receiver: 0.01%
        (Cached): 11% (6.3MB-8.7MB-9.6MB/5.1MB-7.4MB-8.3MB over 4)
  * com.android.chrome / u0a34 / v2272096:
           TOTAL: 0.02%
         Service: 0.01%
        Receiver: 0.02%
        (Cached): 90% (5.1MB-70MB-96MB/3.4MB-66MB-92MB over 15)
  * com.google.android.apps.gcs / u0a94 / v14:
           TOTAL: 0.02%
         Service: 0.02%
        (Cached): 17% (5.8MB-5.9MB-6.0MB/4.6MB-4.7MB-4.8MB over 2)
  * com.android.chrome:privileged_process0 / u0a34 / v2272096:
           TOTAL: 0.02%
         Service: 0.01%
        Receiver: 0.01%
        (Cached): 73% (162MB-163MB-164MB/157MB-157MB-157MB over 13)
  * com.android.chrome:sandboxed_process12 / u0a34 / v2272096:
           TOTAL: 0.02%
         Service: 0.01%
        Receiver: 0.01%
        (Cached): 73% (48MB-49MB-51MB/46MB-47MB-50MB over 13)
  * com.google.android.apps.docs / u0a40 / v51410735:
           TOTAL: 0.01%
        Receiver: 0.01%
        (Cached): 0.45% (10MB-10MB-10MB/9.3MB-9.3MB-9.3MB over 1)
  * com.google.android.deskclock / u0a38 / v303:
           TOTAL: 0.01%
        Receiver: 0.01%
        (Cached): 82% (2.5MB-3.3MB-4.3MB/1.7MB-2.3MB-3.2MB over 13)
  * com.google.android.gm.exchange / u0a69 / v500065:
           TOTAL: 0.01%
          Imp Bg: 0.01%
        (Cached): 27% (3.3MB-3.7MB-3.9MB/2.2MB-2.7MB-2.9MB over 6)
  * com.android.cellbroadcastreceiver / u0a3 / v22:
           TOTAL: 0.01%
         Service: 0.01%
        (Cached): 1.1% (3.5MB-3.5MB-3.5MB/2.5MB-2.5MB-2.5MB over 1)
  * com.coulombtech / u0a106 / v26:
           TOTAL: 0.01%
        Receiver: 0.01%
        (Cached): 21% (4.9MB-5.0MB-5.2MB/3.8MB-3.9MB-4.1MB over 2)
  * com.softcoil.mms / u0a86 / v32:
           TOTAL: 0.01%
        (Cached): 0.25%
  * com.udemy.android / u0a91 / v38:
           TOTAL: 0.01%
        Receiver: 0.01%
        (Cached): 0.75% (9.8MB-9.8MB-9.8MB/8.5MB-8.5MB-8.5MB over 1)
  * com.qualcomm.timeservice / u0a76 / v22:
        (Cached): 16% (2.3MB-2.4MB-2.4MB/1.6MB-1.6MB-1.6MB over 4)
  * com.lge.SprintHiddenMenu / 1000 / v22:
        (Cached): 0.16%
  * com.android.chrome:sandboxed_process13 / u0a34 / v2272096:
        (Cached): 0.01%
  * com.google.android.partnersetup / u0a13 / v22:
        (Cached): 0.14%
  * com.android.musicfx / u0a15 / v10400:
        (Cached): 0.41% (2.5MB-2.5MB-2.5MB/1.6MB-1.6MB-1.6MB over 1)
  * com.android.chrome:sandboxed_process9 / u0a34 / v2272096:
        (Cached): 30% (34MB-34MB-34MB/32MB-32MB-32MB over 9)
  * com.android.chrome:sandboxed_process11 / u0a34 / v2272096:
        (Cached): 7.2% (56MB-56MB-56MB/54MB-54MB-54MB over 3)

Run time Stats:
  SOff/Norm: +32m52s226ms
  SOn /Norm: +2h10m8s364ms
       Mod : +17s930ms
      TOTAL: +2h43m18s520ms

Memory usage:
  Kernel : 265MB (38 samples)
  Native : 73MB (38 samples)
  Persist: 262MB (90 samples)
  Top    : 190MB (325 samples)
  ImpFg  : 204MB (569 samples)
  ImpBg  : 754KB (345 samples)
  Service: 93MB (1912 samples)
  Receivr: 227KB (1169 samples)
  Home   : 66MB (12 samples)
  LastAct: 30MB (255 samples)
  CchAct : 220MB (450 samples)
  CchCAct: 193MB (71 samples)
  CchEmty: 182MB (652 samples)
  Cached : 58MB (38 samples)
  Free   : 60MB (38 samples)
  TOTAL  : 1.9GB
  ServRst: 50KB (278 samples)

          Start time: 2015-04-08 13:44:18
  Total elapsed time: +2h43m18s521ms (partial) libart.so

 

 

 

 

 

 

转载于:https://my.oschina.net/u/269082/blog/801450

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值