Android应用SIGSEGV故障排查:本地存崩溃日志或持续日志监控
解决方案:持续查看日志与离线崩溃日志存储
一、无需重装应用,持续查看实时日志
1. 利用Android Studio的进程绑定与Logcat过滤
别用Android Studio的「重启」按钮(会触发重装),改成在设备上手动重启应用。重启后,在Android Studio的Logcat面板:
- 顶部进程选择器中,找到应用的新进程(包名标识)选中;
- 或者设置Logcat过滤规则为
package:<你的应用包名>,这样不管应用重启多少次,只要进程属于该包名,日志都会自动显示,无需手动切换。
另外,通过「Run > Attach debugger to Android process」绑定到运行中的应用进程,绑定后Logcat会持续输出该进程日志,应用重启后重新绑定新进程即可,全程不会重装应用。
2. 使用ADB命令行日志工具
直接用ADB命令行绕开Android Studio的限制:
- 实时查看应用日志:
adb logcat -s <你的应用包名> - 将日志保存到电脑本地文件,方便后续排查:
adb logcat -s <你的应用包名> > crash_log.txt
应用重启后,该命令会自动捕获新进程的日志,全程不会触发重装。
二、离线运行时将崩溃日志本地存储
1. Java层异常捕获存储
自定义全局异常处理器,捕获Java层未处理异常并写入本地文件:
public class CrashLogger implements Thread.UncaughtExceptionHandler { private final Thread.UncaughtExceptionHandler defaultHandler; private final Context appContext; public CrashLogger(Context context) { appContext = context.getApplicationContext(); defaultHandler = Thread.getDefaultUncaughtExceptionHandler(); } @Override public void uncaughtException(Thread thread, Throwable throwable) { saveCrashLog(throwable); // 交给系统默认处理器处理崩溃 defaultHandler.uncaughtException(thread, throwable); } private void saveCrashLog(Throwable throwable) { File logDir = new File(appContext.getExternalFilesDir(null), "crash_logs"); if (!logDir.exists()) { logDir.mkdirs(); } File logFile = new File(logDir, "crash_" + System.currentTimeMillis() + ".txt"); try (PrintWriter writer = new PrintWriter(new FileWriter(logFile))) { throwable.printStackTrace(writer); } catch (IOException e) { e.printStackTrace(); } } }
在Application类的onCreate()中初始化:
@Override public void onCreate() { super.onCreate(); Thread.setDefaultUncaughtExceptionHandler(new CrashLogger(this)); }
日志会存在设备的Android/data/<你的包名>/files/crash_logs目录下,Android 10+无需额外存储权限。
2. Native层SIGSEGV崩溃捕获存储
SIGSEGV属于原生信号,Java层处理器抓不到,需要在JNI层注册信号处理器:
#include <signal.h> #include <stdio.h> #include <stdlib.h> #include <time.h> #include <unistd.h> #include <android/log.h> #define LOG_TAG "NativeCrash" #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) static void nativeCrashHandler(int sig) { // 构建日志存储路径(应用私有外部存储) char logPath[256]; const char* externalDir = getenv("EXTERNAL_STORAGE"); if (externalDir == NULL) return; snprintf(logPath, sizeof(logPath), "%s/Android/data/<你的包名>/files/crash_logs/native_crash_%ld.txt", externalDir, time(NULL)); FILE* logFile = fopen(logPath, "w"); if (logFile != NULL) { fprintf(logFile, "Native crash triggered by signal: %d\n", sig); // 可选:打印调用堆栈(需链接libunwind等库实现) fclose(logFile); LOGD("Native crash log saved to %s", logPath); } // 恢复系统默认信号处理,避免死循环 signal(sig, SIG_DFL); raise(sig); } void registerNativeCrashHandlers() { signal(SIGSEGV, nativeCrashHandler); signal(SIGABRT, nativeCrashHandler); // 可添加其他需捕获的信号:SIGILL、SIGFPE等 }
在JNI_OnLoad中注册处理器:
jint JNI_OnLoad(JavaVM* vm, void* reserved) { registerNativeCrashHandlers(); return JNI_VERSION_1_6; }
之后用ADB拉取日志到电脑:
adb pull /sdcard/Android/data/<你的包名>/files/crash_logs/ .
内容的提问来源于stack exchange,提问作者Artie Vandelay
相关产品推荐
相关产品推荐

