打印函数的调用堆栈可以直接把问题发生时的函数调用关系打出来,非常有利于理解函数调用、分析、查找问题。
另外,在Android代码里,函数命名很多雷同的,虚函数调用,几个类里的函数名相同等,即使用source insight工具看也未必容易看清函数调用关系。如果用了堆栈打印,很容易看到函数调用逻辑。
我们可用通过以下几种方法,把函数的调用栈打印出来。
1、对于Linux Kernel堆栈的打印
dump_stack() 这个函数打出当前堆栈和函数调用backtrace后接着运行
WARN_ON(x) 这个函数跟dump_stack很像,它有个条件,如果条件满足了就把stack打出来。
打印出来的结果都在kernel log里,一般dmesg命令就可以看到了
2、Native C++
前面确保包含头文件#include<utils/CallStack.h>
Android.mk的库依赖列表(LOCAL_SHARED_LIBRARIES)里包含libutils,一般都已经包含了。
Ø然后在要打印堆栈处加入android::CallStack cs(“haha”);
"haha"是在logcat输出的TAG,这里可以自己定义。如果上下文已经在android namespace里,”android::”前缀就不必加了。
Native C++的输出log可以在logcat里看到。
3、Native C
一个简单方法是用C语言调C++的函数,对,就是extern “C”。
先在项目里加入一个c++文件,比如callstack.cpp,里面是:
#include < utils/CallStack.h>
extern "C" void dumping_callstack(void);
void dumping_callstack(void)
{
//android::CallStack cs("print_stack");
android::CallStack callStack(LOG_TAG, 1)
}
在项目里再加入一个c++的头文件,比如callstack.h,里面是:void dumping_callstack(void);
在Android.mk里源文件列表LOCAL_SRC_FILES里加入callstack.cpp,确保libutils在依赖列表里。
在native C里include callstack.h后直接调用dumping_callstack()就可以了。
这个log也可以在logcat里看到。
4、比较通用的native c(native C++)
在android.mk的shared_libs添加 libutilscallstack
或者在android.bp的 LOCAL_SHARED_LIBRARIES 添加 libutilscallstack
#include < utils/CallStack.h>
CallStack stack;
stack.update();
stack.dump(1);
stack.log(LOG_TAG);
这个log也可以在logcat里看到。
5、对于java有两种方法:
1)、直接抛出异常
Exection e = new Execption("print_stack");
e.prtintStackTrace();
2)、使用logcat
Log.d("TAG","stackTrace:"+ Log.getStackTraceString(new Throwable()));
更多内容尽在公众号:android全贯通