- 开发过程中,最担心的问题就是程序崩溃,而且还不知道崩溃的原因,现在使用Google Breakpad来跟踪崩溃的位置,非常方便;由于目前使用Mac系统开发,Google Breadpad处理Android崩溃日志时需要Linux环境,借助 vagrant 可以非常方便地在Mac使用Ubuntu环境。
1 | $ varant ssh |
执行完上面的命令将会在google-breakpad-read-only/src/processor目录下生成minidump_stackwalk工具,用于导出crash log.google-breakpad-read-only/src/tools/linux/dump_syms目录下生成 dump_syms工具,用于导出符号文件。google-breakpad-read-only/src/client/linux 目录下生成 libbreakpad_client.a。
- 如果编译遇到
“cc1plus: warnings being treated as errors“错误,请将google-breakpad-read-only/Makefile文件中"* -Werror* "删除,重新编译。 - 如果make的时候遇到 “/lib64/libc.so.6: version `GLIBC_2.14’ not found “错误,说明 glibc 没有安装,安装方法请移步:http://my.oschina.net/zhangxu0512/blog/262275
集成 google-breakpad到Android项目中
添加google-beakpad代码:
方法一:
- 拷贝
libbreakpad_client.a到 jni 目录下。 - 打开android项目的 Android.mk文件,在 LOCAL_PATH := $(call my-dir) 下加入如下代码:
- 拷贝
1 | include $(CLEAR_VARS) |
- 方法二:
1 | $(call import-module,google-breakpad-read-only/android/google_breakpad) |
方法三:
- 将 google-breakpad 源代码里面的src文件夹拷贝到项目的jni目录下;
修改Android.mk文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := breakpad_client
LOCAL_CPP_EXTENSION := .cc .cpp
LOCAL_ARM_MODE := arm
LOCAL_SRC_FILES := \
main.cpp \
src/client/linux/crash_generation/crash_generation_client.cc \
src/client/linux/handler/exception_handler.cc \
src/client/linux/handler/minidump_descriptor.cc \
src/client/linux/log/log.cc \
src/client/linux/minidump_writer/linux_dumper.cc \
src/client/linux/minidump_writer/linux_ptrace_dumper.cc \
src/client/linux/minidump_writer/minidump_writer.cc \
src/client/linux/microdump_writer/microdump_writer.cc \
src/client/linux/dump_writer_common/ucontext_reader.cc \
src/client/linux/dump_writer_common/seccomp_unwinder.cc \
src/client/linux/dump_writer_common/thread_info.cc \
src/client/minidump_file_writer.cc \
src/common/android/breakpad_getcontext.S \
src/common/convert_UTF.c \
src/common/md5.cc \
src/common/string_conversion.cc \
src/common/linux/elfutils.cc \
src/common/linux/file_id.cc \
src/common/linux/guid_creator.cc \
src/common/linux/linux_libc_support.cc \
src/common/linux/memory_mapped_file.cc \
src/common/linux/safe_readlink.cc
LOCAL_C_INCLUDES := $(LOCAL_PATH)/src/common/android/include \
$(LOCAL_PATH)/src
LOCAL_C_INCLUDES += $(NDK_ROOT)/sources/cxx-stl/stlport/stlport
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES)
LOCAL_EXPORT_LDLIBS := -llog
LOCAL_LDLIBS := -llog
LOCAL_LDLIBS += $(NDK_ROOT)/sources/cxx-stl/stlport/libs/armeabi/libstlport_static.a
include $(BUILD_SHARED_LIBRARY)
加入对googole-breakpad的引用:
1 | LOCAL_WHOLE_STATIC_LIBRARIES += breakpad_client |
包含搜索路径:
1 | $GOOGLE_BREAKPAD_PATH/src |
本文使用的是第三种集成方法。
添加google breakpad 的 c++代码:
1 |
|
编译C++代码成.so文件(步骤略),通过加载libbreakpad_client.so,调用initial()初始化之后,就开始崩溃捕获。
1 | public class TestCrash { |
解析生成的dmp文件:
- 回到ubuntu环境,建立一个Dump目录:
1 | $ mkdir Dump |
分别将生成的.dmp文件、minidump_stackwalk、dump_syms、android项目下的obj/local/armeabi/libxxx.so库拷贝到Dump目录。
特别说明:libxxx.so文件必须是obj/local/armeabi/ 文件夹下的,这个里面so文件包含了debug信息,相对lib下的so文件来说体积很大,有可能上百兆。
创建好的Dump文件夹路径在“个人 —> ubuntu —> Dump”;
执行生成符号文件命令:
1 | $ cd /Dump |
- 查看libxxx.so.sym文件内容,头部会有,
BB0351B14DDA42A6D36FA6EA358B49D50这样的字符串:
1 | $ head -n1 libxxx.so.sym |
继续执行命令:
1 | $ mkdir -p symbols/libxxx.so/BB0351B14DDA42A6D36FA6EA358B49D50/ |
- 导出崩溃堆栈信息文件( 确保.dmp文件和 symbols目录是同级的 ):
1 | $ ./minidump_stackwalk filename.dmp symbols > crashed.log |
打开 crashed.log 文件:
1 | Thread 0 (crashed) |
- [TestCrash.cpp : 68 + 0x8]:定位到TestCrash.cpp的 第68行,从左到右第8个字符 ,产生的崩溃。
如果没有生成符号文件,则 crashed.log 文件中的信息如下:
1 | Thread 0 (crashed) |
- 这时候就可以在终端中看到是 libxxx.so 中的哪个文件的那一行发生异常了,接下来可以使用日志追踪有问题的代码了。