dump Java和C++函数调用栈

1. java代码中打印堆栈

(1) 通常的方法是使用exception的printStackTrace()方法:

try {
 ...
} catch (RemoteException e) {
  e.printStackTrace();
  ...
}

(2) 测试Demo

class Person {
    public void person_dump_stack() {
        try {
            throw new Exception("my_dump");
        } catch (Exception e) {
          e.printStackTrace();
        }
    }
}

public class Test {
    public static void main(String[] args) {
        Person p = new Person();
        p.person_dump_stack();
    }
}
View Code

执行结果:

# java Test 
java.lang.Exception: my_dump
    at Person.person_dump_stack(Test.java:5)
    at Test.main(Test.java:15)
View Code

 

(3) 当然也可以只打印堆栈不退出,Java代码中插入堆栈打印的方法如下:

Log.d(TAG, Log.getStackTraceString(new Throwable()));

(4) 测试Demo

Android.mk:

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)
LOCAL_SRC_FILES := JavaDump.java
LOCAL_MODULE := java_dump
include $(BUILD_JAVA_LIBRARY)


JavaDump.java:

import android.util.Log;

class Animal {
    public void animal_dump_java_stack() {
        String TAG = "java_dump: ";

        Log.d(TAG, Log.getStackTraceString(new Throwable()));
    }
}

class Person extends Animal {
    public void person_dump_java_stack() {
        animal_dump_java_stack();
    }
}

public class JavaDump {
    public static void main(String args[]) {
        Person person = new Person();
        person.person_dump_java_stack();
    }
}
View Code

执行结果:

1|shell@tiny4412:/system/mytest # dalvikvm -cp ./java_dump.jar JavaDump        
java.lang.UnsatisfiedLinkError: No implementation found for int android.util.Log.println_native(int, int, java.lang.String, java.lang.String) (tried Java_android_util_Log_println_1native and Java_android_util_Log_println_1native__IILjava_lang_String_2Ljava_lang_String_2)
        at android.util.Log.println_native(Native Method)
        at android.util.Log.d(Log.java:139)
        at Animal.animal_dump_java_stack(JavaDump.java:7)
        at Person.person_dump_java_stack(JavaDump.java:13)
        at JavaDump.main(JavaDump.java:22)
View Code

这个效果是最好的,注意打印出来的还有类名和行号,可以避免类的继承关系带来的混淆。

 

补充:感觉下面这个好用一些

new RuntimeException("stack_dump").printStackTrace(); //打印栈回溯

 

 

2. C++代码中打印堆栈

(1) C++也是支持异常处理的,异常处理库中,已经包含了获取backtrace的接口,Android也是利用这个接口来打印堆栈信息的。在Android的C++中,
已经集成了一个工具类CallStack,在libutils.so中。使用方法:

#include <utils/CallStack.h>
...
CallStack stack;
/*void update(int32_t ignoreDepth=1, pid_t tid=BACKTRACE_CURRENT_THREAD);*/
stack.update();
/*void dump(int fd, int indent = 0, const char* prefix = 0) const;*/
stack.dump(); 

(2) 测试Demo

Android.mk:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= CppDump.cpp
LOCAL_SHARED_LIBRARIES := \
    libcutils \
    libutils \
    liblog
LOCAL_MODULE:= cpp_dump
include $(BUILD_EXECUTABLE)


CppDump.cpp:
#define LOG_TAG "dump_cpp: "
#define STDOUT 1
#include <utils/CallStack.h>
using namespace android;

class Person {
public:
    void person_dump_cpp() {
        CallStack stack;
        stack.update();
        stack.dump(STDOUT, 0, LOG_TAG); 
    }
};

int main() {
    Person p1;
    p1.person_dump_cpp();

    return 0;
}
View Code

执行结果:

shell@tiny4412:/system/mytest # ./cpp_dump                                     
dump_cpp: #00 pc 00003035  /system/lib/libbacktrace.so (Backtrace::Unwind(unsigned int, ucontext*)+8)
dump_cpp: #01 pc 0000d061  /system/lib/libutils.so (android::CallStack::update(int, int)+52)
dump_cpp: #02 pc 000003f9  /system/mytest/cpp_dump
dump_cpp: #03 pc 000128f1  /system/lib/libc.so (__libc_init+44)
dump_cpp: #04 pc 0000047c  /system/mytest/cpp_dump
View Code

可以看出效果并不怎么好。

 

补充:可以参考下面

//frameworks/native/libs/binder/IPCThreadState.cpp
CallStack::logStack("oneway spamming", CallStack::getCurrent().get(), ANDROID_LOG_ERROR);

这样C++代码的栈和Java代码的栈都可以打印出来。

 

posted on 2019-05-17 17:31  Hello-World3  阅读(529)  评论(0编辑  收藏  举报

导航