打印调用堆栈

本文介绍了Java中使用Throwable类获取堆栈信息的方法,并提供了Windows环境下通过GetThreadContext、StackWalk等技术进行堆栈追踪的示例代码。文章还分享了如何使用SimpleSymbolEngine类实现地址到符号名、文件名、行号和文件路径的转换,最终生成详细的堆栈跟踪报告。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

java里面可以使用Throwable类来获取堆栈,示例代码如下:

    package name.xu;  
    public class CallStack {  
        public static void printCallStatck() {  
            Throwable ex = new Throwable();  
            StackTraceElement[] stackElements = ex.getStackTrace();  
            if (stackElements != null) {  
                for (int i = 0; i < stackElements.length; i++) {  
                    System.out.print(stackElements[i].getClassName()+"/t");  
                    System.out.print(stackElements[i].getFileName()+"/t");  
                    System.out.print(stackElements[i].getLineNumber()+"/t");  
                    System.out.println(stackElements[i].getMethodName());  
                    System.out.println("-----------------------------------");  
                }  
            }  
        }  
          
    }  

windows下使用GetThreadContext ,StackWalk,SymGetOptions ,SymFunctionTableAccess,示例代码如下:

    #include "SimpleSymbolEngine.h"  
    #include <windows.h>  
    #include <psapi.h>  
    #include <iostream>  
    #include <sstream>  
    #include <cstddef>  
    #include <dbghelp.h>  
    #pragma comment( lib, "dbghelp" )  
    static char const szRCSID[] = "$Id: SimpleSymbolEngine.cpp,v 1.4 2005/05/04 21:52:05 Eleanor Exp {1}quot;;  
    //////////////////////////////////////////////////////////////////////////////////////  
    // Singleton for the engine (SymInitialize doesn't support multiple calls)  
    SimpleSymbolEngine& SimpleSymbolEngine::instance()  
    {  
    static SimpleSymbolEngine theEngine;  
        return theEngine;  
    }  
    /////////////////////////////////////////////////////////////////////////////////////  
    SimpleSymbolEngine::SimpleSymbolEngine()  
    {  
        hProcess = GetCurrentProcess();  
        DWORD dwOpts = SymGetOptions();  
        dwOpts |= SYMOPT_LOAD_LINES | SYMOPT_DEFERRED_LOADS;  
        SymSetOptions ( dwOpts );  
        ::SymInitialize( hProcess, 0, true );  
    }  
    /////////////////////////////////////////////////////////////////////////////////////  
    SimpleSymbolEngine::~SimpleSymbolEngine()  
    {  
        ::SymCleanup( hProcess );  
    }  
    /////////////////////////////////////////////////////////////////////////////////////  
    std::string SimpleSymbolEngine::addressToString( PVOID address )  
    {  
        std::ostringstream oss;  
        // First the raw address  
        oss << "0x" << address;  
        // Then any name for the symbol  
        struct tagSymInfo  
        {  
            IMAGEHLP_SYMBOL symInfo;  
            char nameBuffer[ 4 * 256 ];  
        } SymInfo = { { sizeof( IMAGEHLP_SYMBOL ) } };  
        IMAGEHLP_SYMBOL * pSym = &SymInfo.symInfo;  
        pSym->MaxNameLength = sizeof( SymInfo ) - offsetof( tagSymInfo, symInfo.Name );  
        DWORD dwDisplacement;  
        if ( SymGetSymFromAddr( hProcess, (DWORD)address, &dwDisplacement, pSym) )  
        {  
            oss << " " << pSym->Name;  
            if ( dwDisplacement != 0 )  
                oss << "+0x" << std::hex << dwDisplacement << std::dec;  
        }  
              
        // Finally any file/line number  
        IMAGEHLP_LINE lineInfo = { sizeof( IMAGEHLP_LINE ) };  
        if ( SymGetLineFromAddr( hProcess, (DWORD)address, &dwDisplacement, &lineInfo ) )  
        {  
            char const *pDelim = strrchr( lineInfo.FileName, '//' );  
            oss << " at " << ( pDelim ? pDelim + 1 : lineInfo.FileName ) << "(" << lineInfo.LineNumber << ")";  
        }  
        return oss.str();  
    }  
    /////////////////////////////////////////////////////////////////////////////////////  
    // StackTrace: try to trace the stack to the given output  
    void SimpleSymbolEngine::StackTrace( PCONTEXT pContext, std::ostream & os )  
    {  
        os << "  Frame       Code address/n";  
        STACKFRAME stackFrame = {0};  
        stackFrame.AddrPC.Offset = pContext->Eip;  
        stackFrame.AddrPC.Mode = AddrModeFlat;  
        stackFrame.AddrFrame.Offset = pContext->Ebp;  
        stackFrame.AddrFrame.Mode = AddrModeFlat;  
        stackFrame.AddrStack.Offset = pContext->Esp;  
        stackFrame.AddrStack.Mode = AddrModeFlat;  
        while ( ::StackWalk(  
           IMAGE_FILE_MACHINE_I386,  
           hProcess,  
           GetCurrentThread(), // this value doesn't matter much if previous one is a real handle  
           &stackFrame,   
           pContext,  
           NULL,  
           ::SymFunctionTableAccess,  
           ::SymGetModuleBase,  
           NULL ) )  
        {  
            os << "  0x" << (PVOID) stackFrame.AddrFrame.Offset << "  " << addressToString( (PVOID)stackFrame.AddrPC.Offset ) << "/n";  
        }  
        os.flush();  
    }  

完整的代码到http://www.howzatt.demon.co.uk/articles/SimpleSymbolEngine.zip下载。http://www.codeproject.com/KB/threads/StackWalker.aspx里面也有例子。

 

参考:

http://www.diybl.com/course/3_program/java/javashl/2008119/96739.html

http://topic.youkuaiyun.com/u/20090618/11/7c19832a-975e-4be6-987b-e61d789b31b5.html

http://bbs3.chinaunix.net/viewthread.php?tid=950357&extra=&page=2

http://www.codeproject.com/KB/threads/StackWalker.aspx

http://topic.youkuaiyun.com/u/20070515/21/fc3ebc11-b871-4761-90ae-3c6ddc7b4248.html

http://www.diybl.com/course/3_program/c++/cppjs/20090403/163752_2.html

http://accu.org/index.php/journals/276

http://blog.thepimp.net/archives/how-to-generate-backtraces-on-windows-without-compiler.html

http://blog.youkuaiyun.com/chief1985/article/details/4618492


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值