Android 各類環(huán)境下打印調用堆棧的方法(jni蛉幸,lua破讨,java)

在開發(fā)中旨巷,有時很需要通過打印來判斷函數的調用過程。下面列出幾種比較常用到的打印堆棧的方法添忘。

一、Andorid c++(native層):

方式一:(通過unwind來實現)

#include <unwind.h>
#include <dlfcn.h>
#include <iomanip>
#include <sstream>

namespace {


    struct BacktraceState
    {
        void** current;
        void** end;
    };


    static _Unwind_Reason_Code unwindCallback(struct _Unwind_Context* context, void* arg)
    {
        BacktraceState* state = static_cast<BacktraceState*>(arg);
        uintptr_t pc = _Unwind_GetIP(context);
        if (pc) {
            if (state->current == state->end) {
                return _URC_END_OF_STACK;
            } else {
                *state->current++ = reinterpret_cast<void*>(pc);
            }
        }
        return _URC_NO_REASON;
    }
}


size_t captureBacktrace(void** buffer, size_t max)
{
    BacktraceState state = {buffer, buffer + max};
    _Unwind_Backtrace(unwindCallback, &state);
    return state.current - buffer;
}


void dumpBacktrace(std::ostream& os, void** buffer, size_t count)
{
    for (size_t idx = 0; idx < count; ++idx) {
        const void* addr = buffer[idx];
        const char* symbol = "";
        Dl_info info;
        if (dladdr(addr, &info) && info.dli_sname) {
            symbol = info.dli_sname;
        }
        os << "  #" << std::setw(2) << idx << ": " << addr << "  " << symbol << "\n";
    }
}


void backtraceToLogcat()
{
    const size_t max = 30; // 調用的層數
    void* buffer[max];
    std::ostringstream oss;


    dumpBacktrace(oss, buffer, captureBacktrace(buffer, max));


    __android_log_print(ANDROID_LOG_INFO, "INJECT", "%s", oss.str().c_str());
}

在需要查看的地方調用 backtraceToLogcat() 即可若锁。

它的log如下:

  # 0: 0x9b4524af  
  # 1: 0x9b4530ad  
  # 2: 0x95e1d2fa  
  # 3: 0x9548be48  
  # 4: 0x954f5ca4  
  # 5: 0x953db5ba  
  # 6: 0x96ec8641  
  # 7: 0x96ed9b3c  il2cpp_runtime_invoke (有導出符號的函數)
  # 8: 0x9c5679ef  
  # 9: 0x9c557875  
  #10: 0x9c54f557  
  #11: 0x9c54f77a  

這種方式的好處是不會使程序卡死搁骑,不好的地方在于輸出的log不夠詳細,然后打印出來的地址是絕對的又固,要分析時需要結合/proc/pid/maps 中的基址去定位到函數仲器。

方式二:

直接在JNI_OnLoad方法中通過JavaVM 去獲取到JNIEnv 變量并保存 ,然后再需要的地方調用mEnv->FindClass(NULL) 去打印堆棧信息

這種方法的好處是簡單仰冠,而且它的log信息比較詳細乏冀,除了地址之外,還有所在so的信息洋只。然后它打印出來的地址是相對的辆沦,可以直接在ida按G鍵跳轉到對應的地方。不好的地方在于识虚,會使程序異常退出肢扯。

native: #01 pc 005366fe /system/lib/libart.so(_ZNK3art6Thread4DumpERNSt3__113basic_ostreamIcNS1_11char_traitsIcEEEE+286)
native: #02 pc 003980af /system/lib/libart.so (ZN3art9JavaVMExt8JniAbortEPKcS2+1247)
native: #03 pc 003997e9 /system/lib/libart.so (_ZN3art9JavaVMExt9JniAbortFEPKcS2_z+115)
native: #04 pc 003df47a /system/lib/libart.so (_ZN3art3JNI9FindClassEP7_JNIEnvPKc+2266)
native: #05 pc 0004c0bd /data/data/[packagename]/lib/x86/libtest.so (???)
native: #06 pc 00cc12f9 /data/app/[packagename]/lib/x86/libil2cpp.so (???)
native: #07 pc 0032fe47 /data/app/[packagename]/lib/x86/libil2cpp.so (???)
native: #08 pc 00399ca3 /data/app/[packagename]/lib/x86/libil2cpp.so (???)
native: #09 pc 0027f5b9 /data/app/[packagename]/lib/x86/libil2cpp.so (???)
native: #10 pc 01d6c640 /data/app/[packagename]/lib/x86/libil2cpp.so (???)
native: #11 pc 01d7db3b /data/app/[packagename]/lib/x86/libil2cpp.so (il2cpp_runtime_invoke+56)
native: #12 pc 000b19ee /data/app/[packagename]/lib/x86/libunity.so (???)
native: #13 pc 000a1874 /data/app/[packagename]/lib/x86/libunity.so (???)
native: #14 pc 00099556 /data/app/[packagename]/lib/x86/libunity.so (???)
native: #15 pc 00099779 /data/app/[packagename]/lib/x86/libunity.so (???)
native: #16 pc 00097e7f /data/app/[packagename]/lib/x86/libunity.so (???)

注: 網上提到的一種方法如下:

#include <utils/CallBack.h>

android::CallBack stack;
stack.update()
stack.log("log_tag");

這個方法已經不適用了,因為include的時候會報找不到庫文件担锤。

lua中

直接通過調用 debug.traceback() 即可

Java 中

通過try catch 捕獲一個拋出的異常即可

try{
    throw new Exception("拋出異澄党浚看堆棧"); 
}catch (Exception e){
    Log.i(TAG, "catch異常: ",e); 
} 
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市肛循,隨后出現的幾起案子铭腕,更是在濱河造成了極大的恐慌,老刑警劉巖多糠,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件累舷,死亡現場離奇詭異,居然都是意外死亡熬丧,警方通過查閱死者的電腦和手機笋粟,發(fā)現死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來析蝴,“玉大人害捕,你說我怎么就攤上這事∶苹” “怎么了尝盼?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長佑菩。 經常有香客問我盾沫,道長裁赠,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任赴精,我火速辦了婚禮佩捞,結果婚禮上,老公的妹妹穿的比我還像新娘蕾哟。我一直安慰自己一忱,他們只是感情好,可當我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布谭确。 她就那樣靜靜地躺著帘营,像睡著了一般。 火紅的嫁衣襯著肌膚如雪逐哈。 梳的紋絲不亂的頭發(fā)上芬迄,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天,我揣著相機與錄音昂秃,去河邊找鬼禀梳。 笑死,一個胖子當著我的面吹牛械蹋,可吹牛的內容都是我干的出皇。 我是一名探鬼主播,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼哗戈,長吁一口氣:“原來是場噩夢啊……” “哼郊艘!你這毒婦竟也來了?” 一聲冷哼從身側響起唯咬,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤纱注,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后胆胰,有當地人在樹林里發(fā)現了一具尸體狞贱,經...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年蜀涨,在試婚紗的時候發(fā)現自己被綠了瞎嬉。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡厚柳,死狀恐怖氧枣,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情别垮,我是刑警寧澤便监,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響烧董,放射性物質發(fā)生泄漏毁靶。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一逊移、第九天 我趴在偏房一處隱蔽的房頂上張望预吆。 院中可真熱鬧,春花似錦胳泉、人聲如沸啡浊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至喘先,卻和暖如春钳吟,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背窘拯。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工红且, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人涤姊。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓暇番,卻偏偏與公主長得像,于是被迫代替她去往敵國和親思喊。 傳聞我的和親對象是個殘疾皇子壁酬,可洞房花燭夜當晚...
    茶點故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內容