我的 Android 应用程序 (Java+NDK) 报告了许多由 0xdeadd00d 引起的崩溃(信号)。众所周知,它是 Dalvik VM abort 的简写。这些都没有发生在我的 JNI 调用中,但信号处理发生在原生世界中。但是本机崩溃报告通常报告的内容(寄存器、堆栈)对于调试这些内容没有用。
有没有办法从本机信号处理程序访问 Java 调用堆栈?或者转储最近的 logcat 活动的一部分?
我的 Android 应用程序 (Java+NDK) 报告了许多由 0xdeadd00d 引起的崩溃(信号)。众所周知,它是 Dalvik VM abort 的简写。这些都没有发生在我的 JNI 调用中,但信号处理发生在原生世界中。但是本机崩溃报告通常报告的内容(寄存器、堆栈)对于调试这些内容没有用。
有没有办法从本机信号处理程序访问 Java 调用堆栈?或者转储最近的 logcat 活动的一部分?
解决方案:在信号处理程序中为 deadd00d 引入一个特殊条件。读取 logcat 的最后 1024 字节,将其塞入崩溃日志。
通过这种方式,我得到了一些不错的诊断。
//n is the length of the file tail to read
//Returns # of byte read
size_t ReadLogcat(char *Buf, size_t n)
{
char s[sizeof(s_DataPath) + 30];
//s_DataPath contains the result of Context.getDir("Data")
strcpy(s, "logcat -d -f ");
char *fn = s + strlen(s);
strcat(s, s_DataPath);
strcat(s, "/logcat"); //Temp file for the logcat
size_t r = 0;
system(s); //Dump the snapshot of the logcat into the file called logcat
FILE *f = fopen(fn, "r");
if(f)
{
fseek(f, -n, SEEK_END); //We need the end of the file
r = fread(Buf, 1, n, f);
fclose(f);
}
unlink(fn); //Don't need the logcat file anymore
return r;
}
static void DumpLogcat(FILE *f)
{
char Buf[1024];
size_t r;
if(r = ReadLogcat(Buf, sizeof(Buf)))
{
fputs("\nLogcat:\n", f);
fwrite(Buf, 1, r, f);
}
}
void OnSignal(int signal, siginfo_t *si, void *p)
{
FILE *f = OpenCrashLog(); //opens a file in the data dir; details are irrelevant
//Lots of data dumping here... Version, stack, registers, etc.
//...
if((unsigned)si->si_addr == 0xdeadd00d) //Try and dump some Logcat
DumpLogcat(f);
}