introduce
Now in the daily development of Android, the SO dynamic library is more or less used, especially some third-party SO such as (map SDK, audio and video SDK) and self-developed SDK. I wonder if you have ever thought about such a problem. The user feedback that our APP crashes, At this time, the background did not receive the specific log reported by the customer service, and we did not know where to analyze it, which was the most terrible thing. If there is a log, everything will be better. Let’s analyze how Android catches native crash information.
Framework using
/ / 1. Configuration project/build. Gradle
allprojects {
repositories {
...
maven { url 'https://jitpack.io'}}}Copy the code
//2. app/build.gradle
dependencies {
implementation 'com. Making. Yangkun19921001: YKCrash: 1.0.2'
}
Copy the code
//3
//nativePath: saved DMP logs
//javaPath: Saved Java crash logs
//onCrashListener: Java crash listening callback
// Frame initialization
new Crash.CrashBuild(getApplicationContext())
.nativeCrashPath(nativePath)
.javaCrashPath(javaPath, this)
.build();
Copy the code
The cause of the crash
What’s going to break down
-
Java collapse;
A Java crash is when an uncaught exception occurs in Java code, causing the program to exit abnormally.
-
Native collapse;
This may be due to incorrect address access in Native code, address alignment problems, or active abort, which generate signal and cause the program to exit abnormally.
-
ANR;
- Deadlock;
- IO problem;
- Main thread time-consuming operation;
- Frequent massive GC.
Breakpad Build and Use (MAC)
introduce
Google’s open source Breakpad is recommended. Why? Because it is currently the most mature solution for Native crash capture, many people find Breakpad too complex. In fact, I don’t think Native crash capture is easy.
If you are not familiar with some basic knowledge of the Native crash mechanism, you can take a look at the Android platform Native code crash capture mechanism and implementation
1. Obtain the breakpad source code
-
Website access
-
Making the download
2. Install BreakPad
1. CD Breakpad directory2. Enter./configure && make in the command windowCopy the code
SRC /processor/ minidumP_stackWalk /minidump_stackwalk /minidump_stackwalk /minidump_stackwalk
3. CMakeCompile the source code
The build configuration
apply plugin: 'com.android.library'
android {
.....
defaultConfig {
....
externalNativeBuild {
cmake {
cppFlags "-std=c++11"
}
}
ndk {
abiFilters "armeabi-v7a"."arm64-v8a"."x86"}}... externalNativeBuild { cmake { path"src/main/cpp/CMakeLists.txt"
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
}
Copy the code
Breakpad/SRC source causing the AS in CMake configured directly after the AS/Build/make after the break – Build can generate dynamic so libraries.
Note: the downloaded source code lacks the LSS directory, you can click download to get it
4. Write initialization BreakPad
#include <stdio.h> #include <jni.h> #include <android/log.h> #include "client/linux/handler/exception_handler.h" #include "client/linux/handler/minidump_descriptor.h" #define LOG_TAG "dodoodla_crash" #define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__) #define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) #define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) #define ALOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__) #define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) bool DumpCallback(const google_breakpad::MinidumpDescriptor &descriptor, void *context, bool succeeded) { ALOGD("===============crrrrash================"); ALOGD("Dump path: %s\n", descriptor.path()); return succeeded; } /** extern "C" JNIEXPORT void JNICALL Java_com_devyk_crash_1module_CrashUtils_initBreakpadNative(JNIEnv *env, jclass type, jstring path_) { const char *path = env->GetStringUTFChars(path_, 0); // TODO google_breakpad::MinidumpDescriptor descriptor(path); static google_breakpad::ExceptionHandler eh(descriptor, NULL, DumpCallback, NULL, true, -1); env->ReleaseStringUTFChars(path_, path); } JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { JNIEnv *env; if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) ! = JNI_OK) { return JNI_ERR; } return JNI_VERSION_1_6; }Copy the code
Generate DMP files and locate crash
1. Deliberately writing crash code in app module
/** * cause crash */
void Crash(a) {
volatile int *a = (int *) (NULL);
*a = 1;
}
extern "C"
JNIEXPORT void JNICALL
Java_com_devyk_ykcrash_MainActivity_testCrash(JNIEnv *env, jclass type) {
// TODO
Crash();
}
Copy the code
2. Capture of init native crash
// Configure native crash capture
CrashUtils.initCrash(String nativeCrashPath);
Copy the code
3. Create Crash and generate the xxx.dmp file
Here see the generated xxx. DMP file, the following need to DMP to TXT file a little we can see understand.
4. dmp to txt
-
Will breakpad/SRC/processor/minidump_stackwalk copy into a separate file
-
Run the to TXT command
/ / format ./minidump_stackwalk xxx.dmp >xxx.txt / / case ./minidump_stackwalk /Users/devyk/Data/Project/sample/tempFile/nativeCrash.dmp >crashLog2.txt Copy the code
-
View TXT file exactly what?
Operating System: Android 0.0.0 Linux 4.9.148 #1 SMP PREEMPT Wed Jun 26 04:38:26 CST 2019 AARCH64 CPU: arm64 8 CPUs GPU: UNKNOWN Crash reason: SIGSEGV /SEGV_MAPERR Crash address: 0x0 Process uptime: Thread 0 (crashed) // libcrash-lib.so + 0x5f0 is important. It tells us where the crash occurred in SO, and exactly where the crash occurred. Remember the value 0x5f0. 0 libcrash-lib.so + 0x5f0 x0 = 0x00000078d4ac5380 x1 = 0x0000007fe01fd9d4 x2 = 0x0000007fe01fda00 x3 = 0x00000078d453ecb8 x4 = 0x0000000000000000 x5 = 0x00000078d4586b94 x6 = 0x0000000000000001 x7 = 0x0000000000000001 x8 = 0x0000000000000001 x9 = 0x0000000000000000 x10 = 0x0000000000430000 x11 = 0x00000078d49396d8 x12 = 0x000000795afcb630 x13 = 0x0ef1a811d0863271 x14 = 0x000000795aede000 x15 = 0xffffffffffffffff x16 = 0x00000078b8cb5fe8 x17 = 0x00000078b8ca55dc x18 = 0x0000000000000000 x19 = 0x00000078d4a15c00 x20 = 0x0000000000000000 x21 = 0x00000078d4a15c00 x22 = 0x0000007fe01fdc90 x23 = 0x00000079552cb12a x24 = 0x0000000000000000 x25 = 0x000000795b3125e0 x26 = 0x00000078d4a15ca0 x27 = 0x0000000000000000 x28 = 0x0000007fe01fd9d0 fp = 0x0000007fe01fd9a0 lr = 0x00000078b8ca5614 sp = 0x0000007fe01fd980Copy the code
-
DMP to TXT libcrash-lib.so + 0x5f0;
-
Aarch64 CPU: Arm64 so we find it in the NDK version currently in use / Users/devyk/Data/Android/the NDK/Android – the NDK – r17c/toolchains/aarch64 – Linux – Android 4.9 / prebuilt/Darwin – x86_64 / bin/aarch64 – l Inux-android-addr2line, use the following command to locate the error
/ / 1. The formatAarch64-linux-android-addr2line -f -c -e aarch64-linux-android-addr2line -f -c -e aarch64-linux-android-addr2line -f -c -e/ / 2. The sample /Users/devyk/Data/Android/NDK/android-ndk-r17c/toolchains/aarch64-linux-android-4.9/prebuilt/darwin-x86_64/bin/aarch64-linux-android-addr2line -f -C -e /Users/devyk/Data/Project/sample/github_code/YKCrash/app/build/intermediates/transforms/mergeJniLibs/debug/0/lib/arm64-v8a/libcrash-lib.so 0x5f0 Copy the code
The following video shows the effect of entering the command.
According to the above video, we got the following important information:
// The error function Crash() // The current CPP error line number /Users/devyk/Data/Project/sample/github_code/YKCrash/app/src/main/cpp/crash.cpp:10 Copy the code
So let’s see what CPP line 10 is.
I’m going to crash.
So far we have captured the native layer crash log, and I’m sure you already know it.
-
conclusion
I had no idea breakpad was an open source library, and it was Google’s. Crash capture is necessary because of the amount of C++ code used in the project. Tencent Bugly, which I had been using before Breakpad, stopped because Bugly only supports the Internet environment. Why? Because the products developed by the company are used by the government (the government has a special network belonging to the LOCAL area network).
Finally, I recorded the compilation and use of Breakpad to provide a convenient way for future users, and packaged it into a crash_build_module that can be clicked to download.
Thank you very much
- Android Development Master Course – Zhang Shaowen (Tinker Principal)
- Google breakpad