
1. Native Crash与ANR问题概述在Android开发中Native Crash和ANR(Application Not Responding)是最让开发者头疼的两类问题。Native Crash通常发生在C/C代码层面表现为进程突然终止并生成tombstone文件而ANR则是主线程被阻塞超过5秒导致系统弹出的无响应对话框。这两类问题都会严重影响用户体验甚至导致应用被强制关闭。2. Native Crash的常见类型与诊断2.1 常见Native Crash类型根据Android官方文档常见的Native Crash主要包括以下几种Abort程序主动调用abort()导致的崩溃通常伴随明确的错误信息空指针解引用访问0地址或低地址内存导致的SIGSEGV信号FORTIFY失败C库检测到可能的安全漏洞时触发的保护性崩溃栈保护失败编译器栈保护机制检测到缓冲区溢出非法系统调用seccomp机制阻止了不允许的系统调用2.2 崩溃日志分析要点分析Native Crash日志时需要重点关注以下部分signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0signal表明崩溃的信号类型code信号的具体代码fault addr导致崩溃的内存地址backtrace部分则显示了崩溃时的调用栈backtrace: #00 pc 00019988 /system/lib/libc.so (strlen71) #01 pc 00001a8f /system/xbin/crasher (strlen_null22)3. ANR的产生原因与诊断3.1 ANR触发条件ANR会在以下情况下触发主线程执行耗时操作超过5秒BroadcastReceiver未在10秒内完成onReceive()Service未在20秒内完成启动3.2 ANR日志分析ANR发生时系统会生成包含以下关键信息的日志ANR in com.example.app (com.example.app/.MainActivity) Reason: Input dispatching timed out日志中会包含发生ANR的进程和ActivityANR原因主线程的堆栈信息CPU负载情况4. 预防与解决Native Crash的技术方案4.1 内存安全实践使用智能指针推荐使用std::shared_ptr和std::unique_ptr管理内存边界检查对数组访问进行严格的边界检查空指针检查对所有可能为null的指针进行判空void safe_function(char* ptr) { if (ptr nullptr) { // 处理空指针情况 return; } // 安全使用ptr }4.2 信号处理与崩溃捕获可以注册信号处理器来捕获崩溃信号#include signal.h #include unistd.h void signal_handler(int sig) { // 写入崩溃信息到文件 // 上传崩溃报告 _exit(1); } void install_signal_handlers() { signal(SIGSEGV, signal_handler); signal(SIGABRT, signal_handler); // 其他需要捕获的信号 }4.3 使用AddressSanitizer检测内存问题在Android NDK中启用AddressSanitizerandroid { defaultConfig { externalNativeBuild { cmake { arguments -DANDROID_ARM_MODEarm, -DANDROID_STLc_shared cFlags -fsanitizeaddress -fno-omit-frame-pointer cppFlags -fsanitizeaddress -fno-omit-frame-pointer } } } }5. 预防与解决ANR的技术方案5.1 主线程优化策略异步任务使用AsyncTask、HandlerThread或线程池处理耗时操作减少锁竞争避免在主线程获取可能被长时间持有的锁优化数据库操作使用事务批量处理数据库写入5.2 使用StrictMode检测潜在问题在开发阶段启用StrictModepublic void onCreate() { if (BuildConfig.DEBUG) { StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder() .detectDiskReads() .detectDiskWrites() .detectNetwork() .penaltyLog() .build()); } }5.3 监控ANR的实用方案使用FileObserver监控ANR文件FileObserver anrObserver new FileObserver(/data/anr/) { Override public void onEvent(int event, String path) { if (path ! null path.contains(trace)) { // 处理ANR文件 } } }; anrObserver.startWatching();实现自定义ANR检测器private static final int ANR_THRESHOLD 5000; // 5秒 private Handler mHandler new Handler(); private Runnable mAnrChecker new Runnable() { Override public void run() { if (!mResponded) { // ANR发生 } mResponded false; mHandler.postDelayed(this, ANR_THRESHOLD); } };6. 高级调试技巧与工具链6.1 使用NDK工具链分析Native Crashaddr2line将地址转换为源代码行号aarch64-linux-android-addr2line -e libnative-lib.so 00019988objdump反汇编二进制文件查找问题aarch64-linux-android-objdump -d libnative-lib.so6.2 性能分析工具systrace分析主线程阻塞原因python systrace.py -a com.example.app -o trace.html sched gfx view wmSimpleperfCPU性能分析simpleperf record -p pid -g --duration 106.3 内存分析工具Malloc调试检测内存错误adb shell setprop libc.debug.malloc.options backtrace adb shell setprop libc.debug.malloc.program app_processMalloc钩子跟踪内存分配adb shell setprop wrap.package LIBC_DEBUG_MALLOC_OPTIONSbacktrace logwrapper7. 实战经验与避坑指南7.1 Native开发常见陷阱JNI引用泄漏忘记释放局部和全局引用线程安全错误地在非创建线程调用JNIEnvABI兼容性混合使用不同ABI的库7.2 ANR优化实战技巧避免主线程I/O使用子线程处理文件/网络操作优化布局层次减少View层级和过度绘制合理使用IdleHandler在系统空闲时执行非关键任务Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() { Override public boolean queueIdle() { // 执行低优先级任务 return false; // 返回true保持持续监听 } });7.3 崩溃收集与分析系统建议实现以下崩溃收集功能客户端收集捕获崩溃日志和用户操作路径服务端聚合对相似崩溃进行归并符号化处理自动解析堆栈符号趋势分析监控崩溃率变化8. 系统级优化方案8.1 内核参数调优调整OOM Killer参数echo 1000 /proc/pid/oom_score_adj优化线程调度pthread_setschedparam(pthread_self(), SCHED_FIFO, param);8.2 内存管理优化使用ashmem共享内存int fd ashmem_create_region(shared, size);实现自定义内存池减少频繁分配释放8.3 性能监控框架实现实时性能监控class PerformanceMonitor { private static final int SAMPLE_INTERVAL 1000; void start() { new Thread(() - { while (true) { checkCpuUsage(); checkMemory(); checkMainThreadBlock(); Thread.sleep(SAMPLE_INTERVAL); } }).start(); } private void checkMainThreadBlock() { long start SystemClock.uptimeMillis(); mHandler.post(() - mBlockDetected false); SystemClock.sleep(100); if (mBlockDetected) { // 主线程阻塞警告 } } }