How to Capture and Analyze Android Crashes: From Java Exceptions to Native Minidumps
This technical guide explains the underlying mechanisms of Android crash collection for both Java/Kotlin and native code, outlines a four‑step capture process, compares popular solutions, and provides concrete implementation details—including signal handling, minidump generation, and stack deobfuscation—to help developers reliably record and diagnose app failures.
Background
Stability is crucial for mobile apps; crashes lead to user dissatisfaction, negative reviews, and uninstalls. Android applications often present only a generic “stopped working” prompt, making diagnosis difficult, especially for native crashes and code that has been obfuscated.
Crash Types and Capture Principles
Two main crash categories exist on Android:
Java/Kotlin exceptions run on the Android Runtime (ART). When an uncaught exception such as NullPointerException propagates to the top of a thread, ART invokes the Thread.UncaughtExceptionHandler callback.
Native C/C++ crashes are not managed by ART. They occur when the CPU executes an illegal instruction or accesses invalid memory, causing the Linux kernel to send a signal (e.g., SIGSEGV, SIGILL) to the process.
Signal Details
SIGSEGV (Segmentation Fault) – invalid memory access.
SIGILL (Illegal Instruction) – CPU cannot decode the instruction.
SIGABRT (Abort) – process voluntarily aborts, often via abort() or failed assertions.
SIGFPE (Floating‑Point Exception) – arithmetic errors such as division by zero.
Four‑Step Capture Process
Register a handler : Use sigaction for signals and Thread.setDefaultUncaughtExceptionHandler for Java.
Operate in an async‑signal‑safe environment : Avoid functions like malloc, free, printf, strcpy. Use only safe calls such as write, open, read.
Stack unwinding : When possible, employ libraries like libunwind to reconstruct the call stack.
Generate a minidump : Record registers, raw stack memory, thread list, and loaded modules into a structured minidump file for later offline analysis.
Key Technical Challenges
Capture timing and data persistence : The process is in a fragile state; information must be written synchronously to local storage before termination.
Native crashes as a “black box” : Stack corruption often makes traditional unwinding unreliable, so a full snapshot (minidump) is required.
Obfuscation and symbolization : ProGuard/R8 replace class and method names with meaningless tokens, and native binaries contain only raw addresses. Proper mapping files ( mapping.txt for Java, DWARF info for native) are needed to translate back to readable symbols.
Industry Solutions
Google Breakpad/Crashpad – the de‑facto standard for native crash capture, providing end‑to‑end minidump generation and symbolication tools.
Firebase Crashlytics & Sentry – SaaS platforms that wrap the low‑level capture logic and offer cloud dashboards for aggregation and analysis.
xCrash – an open‑source library supporting both Java and native crashes with advanced stack recovery.
Implementation Overview
Java/Kotlin Crash Handling
Register a global handler that records exception type, message, stack trace, thread name, and timestamp, then persists the data synchronously using SharedPreferences.edit().commit(). The original handler is invoked afterwards to preserve default system behavior.
@Override
public void uncaughtException(Thread thread, Throwable throwable) {
try {
CrashData crashData = collectCrashData(thread, throwable);
saveCrashData(crashData);
} finally {
if (originalHandler != null) {
originalHandler.uncaughtException(thread, throwable);
}
}
}
private void saveCrashData(CrashData data) {
// Use synchronous commit to guarantee persistence
prefs.edit().putString("last_crash", data.toJson()).commit();
}Native Crash Handling
At application start, load a native library and call NativeBridge.initialize(dumpPath). The library registers signal handlers for SIGSEGV, SIGILL, SIGABRT, and SIGFPE using sigaction with the SA_SIGINFO flag to obtain a siginfo_t structure. Inside the handler only async‑signal‑safe operations are performed: write registers, stack memory, and module list to a .dmp file.
public void start() {
// Initialize native signal handlers
NativeBridge.initialize(crashDir.getAbsolutePath());
// Process any leftover dumps on next launch
new Thread(this::processExistingDumps).start();
}
private void processExistingDumps() {
File[] dumpFiles = crashDir.listFiles();
for (File dumpFile : dumpFiles) {
reportToServer(dumpFile);
dumpFile.delete();
}
}
static class NativeBridge {
static { System.loadLibrary("crash-handler"); }
public static native void initialize(String dumpPath);
}Minidump Processing
On the next app launch the framework scans the dump directory, parses each minidump (using Breakpad tools such as dump_syms and minidump_stackwalk on the server), extracts thread contexts, registers, and module information, uploads the report, and deletes the file.
Java Stack Deobfuscation
When code is minified with ProGuard/R8, a mapping.txt file maps obfuscated names to original class and method names. A deobfuscation tool reads each stack line, extracts the obfuscated class, method, and line number, looks up the original names in mapping.txt, and restores the correct source location.
Native Stack Symbolication
For native addresses, the unstripped .so contains DWARF debug information. The NDK utility
addr2line -C -f -e /path/to/unstripped/libtest-native.so 0x3538translates the address to a function name and source file line, demangling C++ symbols as needed.
# Using NDK addr2line
# -C: demangle C++ symbols
# -f: show function name
# -e: specify the unstripped library
addr2line -C -f -e /path/to/unstripped/libtest-native.so 0x3538Conclusion
The article dissects Android crash capture, addresses three core difficulties—capture timing, the black‑box nature of native crashes, and stack obfuscation—and proposes a unified framework that leverages Java’s UncaughtExceptionHandler and Breakpad‑based native handling to reliably collect, persist, and later analyse crash data.
Alibaba Cloud Native
We publish cloud-native tech news, curate in-depth content, host regular events and live streams, and share Alibaba product and user case studies. Join us to explore and share the cloud-native insights you need.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
