Android Crash Log Errors: Explained
Crashes on Android can be exceedingly stymie for users, so much so that after suffering as little as two accidents, the conventional user will uninstall your app. Fortunately, the Android Framework provisions some great tools for debugging accidents, and renders several beneficial crash records that developers can speak to determine what generated that critical issue. In this blog announce we’ll cover the three most important crash enters used by the system: exclusion load retraces, ANR retraces, and NDK tombstones.
Exclusion Stack trace
JVM stack traces are the most common type of crash that ordinary Android applications will encounter, as the majority of apps are written in either Kotlin or Java. In JVM communications, an Exception is shed in exceptional circumstances, and contains debug informed about the error condition that went wrong, such as a load vestige with file/ thread quantity information, and an error message. \ n
If an app hasn’t got a crash reporting SDK lay, then the next best method for retrieving disintegrate records is to use adb to goal logcat. This is a convenient method if physical access to the device is an option, because the default UncaughtExceptionHandler in Android apps photographs out the part load retrace to Logcat before closing the process, signifying the slam is effectively entered out to an accessible location for developers.
ANR Trace
ANRs( Application Not Responding) is the case when an employment does not respond to user input for a noticeable period of time. The evident effect of this is that an app has’ frozen’ from a user’s perspective, which can be immensely disheartening. Common induces include performing disk speaks/ writes on the prime thread, and other long-running assignments, which impedes the User Interface from updating in response to user input. \ n
If the app is in the foreground, after approximately five seconds a dialog will be shown which allows the user to kill the app. At this top a detect including details of the ANR will be written to disk, from which valuable intelligence for debugging can be recovered. Again, this requires physical access to the device unless you have a crash reporting SDK installed that supports ANR detection.
Tombstone
Tombstone crash logs are written when a native slam in C/ C ++ code occurs in an Android application. The Android platform writes a vestige of all the running strands at the time of the clang to/ data/ gravestones, along with additional information for debugging, such as information about memory and open folders. Memorials are the closest to the metal in terms of information, as they will record items such as raw memory domiciles, and as such can be a bit trickier to understand unless you’re familiar with debugging native code. Again, tombstones involve physical be made available to a rooted machine in order to be read.
How to get Crash Logs from an Android device
As a prerequisite to all these steps, you should have installed Android Studio and included the command line tools to your route. These neighbourhood methods make use of the adb tool. You should also have a device or emulator connected which has had developer options enabled. \ n
::: info Note: if you are cozy abusing the Device File Explorer in Android Studio instantly, you are eligible to open manoeuvre files directly from there rather than employ adb pull.
:: ๐ TAGEND Exclusion Stack trace
By default, exclusion load finds are printed out to the Logcattool on Android devices. It is possible to retrieve crash logs via the following steps: \ n
Run the following command
\
adb logcat AndroidRuntime: E *: S
\
Trigger a gate-crash on the device. The stack retrace will show up as new text in the terminal.
Save the terminal output to a document of your preference for inspection later
\
If a clang has existed recently on the design, you can skip step 2. This is because Logcat retains a buffer of recent enters which should include the exception. This is time sensitive however – so if you’re looking for a crash from a date ago, that info may be gone forever unless you use a sound reporting tool such as Bugsnag.
ANR Trace
Trigger an ANR on the device.
Run the following command, changing the end with a file of your choice
\
adb pull/ data/ anr/ traces.txt
\
Inspect the information in the ANR crash log by opening the saved file \ n
Alternatively, you can inspect summary ANR information by running the following command
\
adb logcat ActivityManager: E *: S
Tombstone \ n
Root your machine or emulator so that you can access the memorial index.( Beware when rooting devices, as this pace can potentially brick your telephone)
Trigger a native gate-crash on the device.
Run the following command to determine what tombstone crash logs are present on the device
\
adb ls/ data/ memorials
\
Run the following command, replacing the destination with a file of your selection. tombstone_0 1 is shown as an example filename here, that would be obtained in the previous step
\
adb drag/ data/ memorials/ tombstone_0 1
\
Inspect the information in the Tombstone crash log by reopen the saved file
Making sense of Android Crash Log Data Exception Stack trace
Reading a JVM stack trace can be intimidating at first, but by ruin it down into its constituent parts the assignment becomes fairly easy. Let’s walk through it step by step, with the following RuntimeExceptionthat has been hurled in an example application: \ n
2019-08-27 16:10: 28.303 10773 -1 0773/ com.bugsnag.android.example E/ AndroidRuntime: FATAL EXCEPTION: main
Process: com.bugsnag.android.example, PID: 10773
java.lang.RuntimeException: Fatal Crash
at com.example.foo.CrashyClass.sendMessage( CrashyClass.java: 10)
at com.example.foo.CrashyClass.crash( CrashyClass.java: 6)
at com.bugsnag.android.example.ExampleActivity.crashUnhandled( ExampleActivity.kt: 55)
at com.bugsnag.android.example.ExampleActivity$ onCreate $1. invoke( ExampleActivity.kt: 33)
at com.bugsnag.android.example.ExampleActivity$ onCreate $1. mention( ExampleActivity.kt: 14)
at com.bugsnag.android.example.ExampleActivity$ sam$ android_view_View_OnClickListener $0. onClick( ExampleActivity.kt)
at android.view.View.performClick( View.java: 5637)
at android.view.View$ PerformClick.run( View.java: 22429)
at android.os.Handler.handleCallback( Handler.java: 751)
at android.os.Handler.dispatchMessage( Handler.java: 95)
at android.os.Looper.loop( Looper.java: 154)
at android.app.ActivityThread.main( ActivityThread.java: 6119)
at java.lang.reflect.Method.invoke( Native Method)
at com.android.internal.os.ZygoteInit$ MethodAndArgsCaller.run( ZygoteInit.java :8 86)
at com.android.internal.os.ZygoteInit.main( ZygoteInit.java: 776)
\ The first place to start is towards the top of our disintegrate record. Here we can see the process ID that the system appointed the executing app, together with the parcel mention, which can be useful when correlating against other knowledge attained via logcat. In our speciman app, the parcel word is “com.bugsnag.android.example”: \ n
Process: com.bugsnag.android.example, PID: 10773
\ The next beneficial case of information is the exception class. In Java/ Kotlin, all exceptions and wrongdoings are courses which provide Throwable or one of Throwable’s subclasses, and each objection class can have a different semantic entail. For pattern, a developer may wish to throw an IllegalStateException if the program registered an unexpected position, or an IllegalArgumentException if a used attempted to save null as their reputation. In our suit, we’ve thrown a RuntimeException, whose fully qualified class name is exposed below ๐ TAGEND
\
java.lang.RuntimeException: Fatal Crash
\ The error message is also engraved to the crash log, which can be very useful for furnishing additional debug message. In our contingency, we have just equipped the text “Fatal Crash”, but we could equally overtakes the values of our variables at the time of the slam if we wanted further information for debugging.
\ The next thing in our crash record is the juicy part of the information – a stack find of the weave where the exception resulted. Looking at the top stackframe will usually allow us to find exactly where the error was thrown from, and the encloses below it will allow us to observe what the program state was at the time of the gate-crash. The top stackframe shall read as follows ๐ TAGEND
\ n
com.example.foo.CrashyClass.sendMessage(CrashyClass.java:10)
\ We can immediately see that this contains some very useful information. We are given the class, “com.example.foo.CrashyClass”, so we can open the source file and hunt for a defect there. We’re too given the method name, “sendMessage”, and the line number of the accident, 10, so we can pinpoint accurately in our beginning where certain exceptions was thrown from.
\ Understanding the crash enter from this target onwards is a case of reading the stack frames below, which are in the order in which the methods were originally called. Consider the lesson below ๐ TAGEND
\
at com.example.foo.CrashyClass.sendMessage( CrashyClass.java: 10)
at com.example.foo.CrashyClass.crash( CrashyClass.java: 6)
at com.bugsnag.android.example.ExampleActivity.crashUnhandled( ExampleActivity.kt: 55)
\ Starting at the top, we can tell that “sendMessage” was invoked by “crash”, which was in turn invoked by a approach referred “crashUnhandled”, which seems to be the beginning of our disintegrate. Of track, the full objection stack trace was somewhat more complex, and also involved method calls in the Android framework, but the basic principle remains the same.
\ An important greenback is that in production, apps are often obfuscated by tools such as Proguard which can mean the original representations are not present, and the stack find becomes illegible. Fortunately, most crash reporting assistances cater plugins that automatically upload a mapping record that contains the information necessary to symbolicate crash reports from your product apps.
ANR Trace
ANR tracings contain a very large amount of information. As an ANR can potentially be caused by multiple apps bickering for a limited number of resources, the full disintegrate enter contains load marks for numerou different treats. This full information can be very useful for debugging when all else miscarries, but the majority of cases the summing-up ANR information printed into Logcat is sufficient to debug the error. Consider the following entry ๐ TAGEND
\
2019-08-27 16:12: 57.301 1717 -1 733/ system_process E/ ActivityManager: ANR in com.bugsnag.android.example( com.bugsnag.android.example /. ExampleActivity)
PID: 10859
Reason: Input dispatching seasoned out( Waiting to send non-key event because the stroked space has not finished processing sure-fire input incidents that were delivered to it over 500.0 ms ago. Wait queue length: 33. Wait queue head age: 6178.1 ms .)
Load: 0.32/ 0.62/ 0.37
CPU usage from 323086 ms to -1ms ago( 2019 -0 8-27 13:16: 43.467 to 2019 -0 8-27 16:12: 54.131 ):
5.7% 1717/ system_server: 2.6% consumer+ 3% grain/ defects: 21251 adolescent
4.7% 10392/ com.bugsnag.android.example: 1.3% used+ 3.3% seed/ mistakes: 587 minor
3.9% 2375/ com.google.android.gms: 2.9% used+ 0.9% grain/ omissions: 71377 minor 51 major
3.1% 16/ ksoftirqd/ 2: 0% consumer+ 3.1% seed
2.5% 2254/ com.google.android.googlequicksearchbox: scour: 1.1% user+ 1.4% grain/ faultings: 10193 child
1.2% 10427/ kworker/ u8: 0: 0% user+ 1.2% kernel
0.9% 8990/ kworker/ u8: 2: 0% customer+ 0.9% grain
0.8% 1342/ surfaceflinger: 0.1% customer+ 0.7% grain/ demerits: 35 child
0.5% 1344/ adbd: 0% user+ 0.4% grain/ omissions: 8471 child
0.4% 1896/ com.google.android.gms.persistent: 0.3% used+ 0% grain/ flaws: 1106 minor
0.4% 1288/ logd: 0.1% used+ 0.3% grain/ mistakes: 43 minor
0.3% 1806/ com.android.systemui: 0.2% user+ 0% seed/ fractures: 404 child
0.2% 1916/ com.android.phone: 0.1% used+ 0% grain/ demerits: 203 adolescent
0.2% 1410/ audioserver: 0% used+ 0.1% grain/ defects: 119 adolescent
0.1% 10429/ kworker/ u8: 3: 0% consumer+ 0.1% seed
0.1% 10378/ com.google.android.apps.photos: 0.1% user+ 0% grain/ demerits: 426 child
0.1% 8/ rcu_preempt: 0% used+ 0.1% grain
0% 1396/ jbd2/ dm-0- 8: 0% user+ 0% seed
0% 2179/ com.google.android.apps.nexuslauncher: 0% used+ 0% grain/ faultings: 802 minor 1 major
0% 1409/ zygote: 0% user+ 0% seed/ flaws: 857 child
0% 3951/ com.android.defcontainer: 0% customer+ 0% grain/ defects: 265 child
0% 10137/ kworker/ u9: 0: 0% used+ 0% seed
0% 1987/ wpa_supplicant: 0% consumer+ 0% seed
0% 10205/ com.google.android.apps.docs: 0% used+ 0% grain/ mistakes: 50 minor
0% 1378/ dmcrypt_write: 0% user+ 0% kernel
0% 2111/ com.google.process.gapps: 0% customer+ 0% kernel/ fractures: 356 adolescent
0% 3882/ com.android.printspooler: 0% customer+ 0% grain/ faults: 241 minor
0% 8829/ kworker/ u9: 2: 0% customer+ 0% seed
0% 9808/ kworker/ u9: 4: 0% customer+ 0% seed
0% 19/ movement/ 3: 0% user+ 0% seed
0% 1420/ rild: 0% customer+ 0% grain
0% 10138/ kworker/ u9: 1: 0% consumer+ 0% grain
0% 1339/ lmkd: 0% user+ 0% kernel
0% 1419/ netd: 0% used+ 0% grain/ mistakes: 59 adolescent
0% 1793/ com.android.inputmethod.latin: 0% consumer+ 0% seed/ fractures: 12 adolescent
0% 10146/ com.android.gallery3d: 0% used+ 0% grain/ omissions: 95 adolescent
0% 10181/ android.process.acore: 0% customer+ 0% kernel/ faults: 52 child
0% 1281/ kworker/ 0:1 H: 0% consumer+ 0% kernel
0% 10162/ kworker/ 2:1: 0% customer+ 0% seed
0% 10348/ com.google.android.partnersetup: 0% user+ 0% seed/ defects: 92 minor
0% 20/ ksoftirqd/ 3: 0% customer+ 0% kernel
0% 10308/ android.process.media: 0% customer+ 0% kernel/ flaws: 16 adolescent
0% 1336/ healthd: 0% consumer+ 0% grain
0% 1354/ logcat: 0% consumer+ 0% kernel
0% 1709/ hostapd: 0% used+ 0% seed
0% 3/ ksoftirqd/ 0: 0% used+ 0% kernel
0% 1341/ servicemanager: 0% user+ 0% seed
0% 2091/ com.google.android.ext.services: 0% used+ 0% grain/ faultings: 10 adolescent
0% 10475/ com.google.android.apps.photos: CameraShortcut: 0% user+ 0% kernel/ mistakes: 29 child
0% 4/ kworker/ 0:0: 0% consumer+ 0% grain
0% 12/ ksoftirqd/ 1: 0% user+ 0% kernel
0% 1422/ fingerprintd: 0% consumer+ 0% seed
0% 1591/ dhcpclient: 0% used+ 0% kernel
0% 1706/ ipv6proxy: 0% customer+ 0% seed
0% 1913/ sdcard: 0% customer+ 0% grain
0% 2137/ com.google.android.googlequicksearchbox: interactor: 0% consumer+ 0% kernel/ defects: 3 child
0% 687/ kworker/ 1:1: 0% consumer+ 0% grain
0% 1297/ vold: 0% used+ 0% kernel/ omissions: 10 adolescent
0% 1413/ installd: 0% used+ 0% seed/ mistakes: 35 adolescent
0% 1 // init: 0% user+ 0% grain
0% 11/ movement/ 1: 0% customer+ 0% grain
0% 466
\ First off, the clang log contain information on which process on the system suffered an ANR, and commits the process ID and bundle figure, which comes in useful when noticing the relevant load retraces in the more detailed ANR trace ๐ TAGEND
\
E/ActivityManager: ANR in com.bugsnag.android.example( com.bugsnag.android.example /. ExampleActivity)
PID: 10859
\ The Android framework imparts us a reason for the ANR. In such cases, the user touched the screen several times, and the dispatch queue waited for over 6 seconds without presenting a evident response to these signature occurrences. This represents a very bad user experience that would be noticeable as the whole app would appear to freeze from a user’s perspective ๐ TAGEND
\
Reason: Input dispatching went out( Waiting to send non-key event because the touched space has not finished processing sure-fire input contests that were delivered to it over 500.0 ms ago. Wait queue length: 33. Wait queue head age: 6178.1 ms .)
\ Finally, we’re given some CPU load information. While some ANRs have simple makes such as play-act IO on the primary weave, this is not always the case. Sometimes an ANR can occur on a low-end device due to a lot of resource-hungry apps playing for CPU, so determining whether there are other apps exerting lots of resources at the same time as our lotion can be very helpful ๐ TAGEND
\
CPU usage from 323086 ms to -1ms ago( 2019 -0 8-27 13:16: 43.467 to 2019 -0 8-27 16:12: 54.131 ):
5.7% 1717/ system_server: 2.6% used+ 3% seed/ glitches: 21251 minor
4.7% 10392/ com.bugsnag.android.example: 1.3% used+ 3.3% seed/ faults: 587 adolescent
3.9% 2375/ com.google.android.gms: 2.9% customer+ 0.9% seed/ demerits: 71377 child 51 major
3.1% 16/ ksoftirqd/ 2: 0% user+ 3.1% kernel
2.5% 2254/ com.google.android.googlequicksearchbox: research: 1.1% consumer+ 1.4% grain/ omissions: 10193 child
Tombstone
Like ANR tracings, headstones also contain a very large amount of information that wouldn’t be possible to walk through entirely. We’ll consider a truncated lesson, which shows the most important information near the top ๐ TAGEND
\
ABI: ‘x8 6’ pid: 15300, tid: 15300, epithet: android.example >>> com.bugsnag.android.example <<< signal 11 (SIGSEGV) eax b19aa650 ebx b19abfd8 ecx 00000005 edx b32a1230 esi 99365d7e edi bf9c2338 xcs 00000073 xds 0000007b xes 0000007b xfs 0000003b xss 0000007b eip b19aa688 ebp bf9c2148 esp bf9c2140 flags 00010296 backtrace: #00 pc 00000688 /data/app/com.bugsnag.android.example-2/lib/x86/libentrypoint.so (crash_write_read_only+40) #01 pc 000006ca /data/app/com.bugsnag.android.example-2/lib/x86/libentrypoint.so (Java_com_bugsnag_android_example_ExampleActivity_doCrash+42) #02 pc 003e9d3c /data/app/com.bugsnag.android.example-2/oat/x86/base.odex (offset 0x399000) stack: bf9c2100 b32dc140 [anon:libc_malloc] bf9c2104 b3159f5c /system/lib/libart.so bf9c2108 b315abb3 /system/lib/libart.so bf9c210c b315ab82 /system/lib/libart.so bf9c2110 b315ab69 /system/lib/libart.so bf9c2114 b716ced4 /dev/ashmem/dalvik-LinearAlloc (deleted) bf9c2118 b328b400 [anon:libc_malloc] bf9c211c b312b721 /system/lib/libart.so (_ZN3art14JniMethodStartEPNS_6ThreadE+17) bf9c2120 00430000 bf9c2124 00590000 bf9c2128 b328b400 [anon:libc_malloc] bf9c212c b32a1230 [anon:libc_malloc] bf9c2130 b32b00c0 [anon:libc_malloc] bf9c2134 b328b400 [anon:libc_malloc] bf9c2138 00000043 bf9c213c b19aa66e /data/app/com.bugsnag.android.example-2/lib/x86/libentrypoint.so (crash_write_read_only+14) #00 bf9c2140 bf9c2200 bf9c2144 b19aa650 /data/app/com.bugsnag.android.example-2/lib/x86/libentrypoint.so bf9c2148 bf9c2178 bf9c214c b19aa6cb /data/app/com.bugsnag.android.example-2/lib/x86/libentrypoint.so (Java_com_bugsnag_android_example_ExampleActivity_doCrash+43) #01 bf9c2150 00430000 bf9c2154 00000013 bf9c2158 05980a40 bf9c215c bf9c219c bf9c2160 b32a1230 [anon:libc_malloc] bf9c2164 0000000c bf9c2168 bf9c21cc bf9c216c b2bc803f /system/lib/libart.so (art_jni_dlsym_lookup_stub+15) bf9c2170 b328b400 [anon:libc_malloc] bf9c2174 0000000c bf9c2178 bf9c21cc bf9c217c 994aed3d /data/app/com.bugsnag.android.example-2/oat/x86/base.odex #02 bf9c2180 b32a1230 [anon:libc_malloc] bf9c2184 bf9c219c bf9c2188 05980a40 bf9c218c 00000001 bf9c2190 b716ced4 /dev/ashmem/dalvik-LinearAlloc (deleted) bf9c2194 bf9c2c24 bf9c2198 00000001 bf9c219c 12c7b450 /dev/ashmem/dalvik-main space (deleted) bf9c21a0 00000006 bf9c21a4 b31fbb74 /system/lib/libart.so bf9c21a8 bf9c2238 bf9c21ac b2f3a0a4 /system/lib/libart.so (_ZNK3art7OatFile8OatClass19GetOatMethodOffsetsEj+100) bf9c21b0 bf9c21cc bf9c21b4 99365d7e /data/app/com.bugsnag.android.example-2/oat/x86/base.odex bf9c21b8 bf9c2338 bf9c21bc b2bc9263 /system/lib/libart.so (art_quick_invoke_stub+339)
\Breaking it down
\
ABI: ‘x86’pid: 15300 >> com.bugsnag.android.example <<<
\ We’re given information about the native error, which in this case was due to a SIGSEGV signal being raised. This contains the address where the fracture was triggered, together with assembly directions ๐ TAGEND
\
signal 11( SIGSEGV ), code 2( SEGV_ACCERR ), flaw addr 0xb19aa650
eax b19aa650 ebx b19abfd8 ecx 00000005 edx b32a1230
esi 99365 d7e edi bf9c2338
xcs 00000073 xds 0000007 b xes 0000007 b xfs 0000003 b xss 0000007 b
eip b19aa688 ebp bf9c2148 esp bf9c2140 pennants 00010296
\ The rest of the draw contains typifies which were being performed at the time of the hurtle, which can be symbolicated utilizing debug message in your application’s shared object documents, a feature that Bugsnag achieves automatically with a gradle plugin integration.
Next Steps
While getting crash logs of your Android device manually can be very useful in certain situations, it’s possible to automate collection of accident enters by installing a crash reporting SDK such as Bugsnag’s Android SDKin your application. Crash reporting SDKs automatically identify JVM gate-crashes, NDK gate-crashes, and ANRs, and automatically deliver a diagnostic report about the mistake to a entanglement dashboard. \ n
There are several advantages to collecting crash records automatically. You might not always have access to a maneuver, particularly if a accident has occurred on an end-user’s device, or if you are employing a 3rd defendant Quality Assurance firm, they are not able to have the necessary tools installed to obtain crash logs manually from a test device. Crash reporting SDKs volunteer automated reporting of mistakes from your yield work, so that you can gain an immediate penetration into how many useds have an effect on a glitch and determine how to fix it with diagnostic message. \ n
A great advantage of accident reporting SDKs is that it’s possible to attach custom metadata to an error report. On-device crash enters are limited by the amount of information that the Android framework can muster, but there is no such limited when it is necessary to 3rd party tools. For precedent, Bugsnag will automatically captivate breadcrumbs on Android of lifecycle events and common system broadcasts, which can help track down those difficult imperfections that are related to unexpected regime in a lifecycle event. \ n
Crash reporting works likewise give powerful search and segmentation. Perhaps a defect is only occurring on specific OS copies, or a critical error with In-App-Purchases is affecting the conversion charge of your paid customers. By adding custom-built metadata to error reports, it’s possible to segment and search for the important bugs, so that you can prioritise what delivers appreciate for your business, rather than wasting time manually comparing disintegrate logs from dozens of machines yourself.
Read more: hackernoon.com
Recent Comments