Throwable的使用--取得方法的调用堆栈

原创 2005年05月31日 15:55:00

使用纯Jdbc设计数据库连接池的时候,设计了数据库连接类,其对象是可重用的,所有的使用者依靠状态标记来获取该对象:
每一个使用者使用前要判断状态,如果可用的话,设置成占用状态,然后开始使用,用完恢复成可用状态。
这就需要每一个使用者用完后要恢复状态,如果没有恢复状态,该对象就无法再被使用(这个过程当然是要同步的)。
由于恢复状态需要coder调用,coder可能会遗忘而没有恢复状态(这个遗忘有可能是确确实实的遗忘,也有可能是编码不当,比如没有考虑到的异常),这会造成资源的浪费。
这个错误如果频繁的话,对于DB Connection来说是一件非常恐怖的事情。

为了处理遗忘而没有恢复状态的,可以使用超时机制,使用thread来进行定时扫描,检测超时使用的对象(超时有可能是没有恢复状态,也有可能确实是运行需要更长的时间,如果不重要的话而且不是经常发生的话,可以简单的“宁枉勿纵” ~_~)。


如果超时的原因确实是没有恢复状态,为了改正这个错误,只靠超时机制是解决不了这个问题的,需要定位到其调用上。
改正可以依赖于人工的查看代码。但这有很大弊端,对于大量的调用要耗费大量的人工,而且如果这个错误比较隐蔽,有可能人工查看都未必能找出来。
另一种就是我们可以自动的进行定位,如果知道调用堆栈,就知道了特定方法的调用


这就是本文的目的--取得Java的调用堆栈。

谈到Java的调用堆栈,很自然的想到经典一行程序 e.printStackTrace()
Exception也提供把异常信息输出到给定的PrintWriter对象或者PrintStream对象中
void printStackTrace(PrintWriter s)
void printStackTrace(PrintStream s)

因此我们可以使用如下的方法取得调用堆栈的信息
StringWriter sw=new StringWriter();
Exception e=new Exception("Debug Mode");
e.printStackTrace(new PrintWriter(sw));

但这个结果还是需要进行进一步处理的,查看printStackTrace的源代码,原来printStackTrace输出是对getOurStackTrace()返回的StackTraceElement[]进行遍历然后输出的结果,到这里找到了我们解决我们问题的方法
Throwable提供 public StackTraceElement[] getStackTrace() 返回当前调用堆栈,函数里面就一句
return (StackTraceElement[]) getOurStackTrace().clone();
至此我们可以调用Throwable对象的getStackTrace()方法得到堆栈,然后自己处理。
下面的代码就足够了
Throwable throwable=new Throwable();
StackTraceElement[] elements=throwable.getStackTrace();

很明显,这里的获取调用堆栈,只是为了为了监视调用的,对正常的业务来说完全是多余的,而且返回对象的clone,都是无益于业务的,因此,为了解决我的问题,设置Debug标记标识当前处于Release Mode还是Debug Mode,只在Debug Mode才处理堆栈信息
实例如下:
////////////////////////////////////////////////////////////////////////////////////////
public class CallStackUtil
 {
    private static boolean debugMode=false;

    public static boolean isDebugMode()
    {
        return debugMode;
    }

    public static void setDebugMode(boolean debugMode)
    {
        CallStackUtil.debugMode = debugMode;
    }

    public static StackTraceElement[] getCurrentCallStack()
    {
        if(debugMode)
            System.out.println("Debug Mode");
        else
            System.out.println("Normal Mode");
        if(debugMode)
        {
            Throwable throwable=new Throwable();
            return throwable.getStackTrace();
        }
        return null;
    }
}
////////////////////////////////////////////////////////////////////////////////////////
public class test
 {
    public static void main(String[] para)
    {
        CallStackUtil.setDebugMode(true);
       caller();
    }
    public static void methodMonitored()//被监控的方法
    {
        StackTraceElement[]  elements=CallStackUtil.getCurrentCallStack();
        if(elements!=null)
            if(elements.length>2)
                System.out.println(elements[2].toString().split("//(")[0]+"() calling "+elements[1].toString().split("//(")[0]+"()!");
    }
    public static void caller()
    {
      methodMonitored();
    }
}
////////////////////////////////////////////////////////////////////////////////////////
运行输出结果:
Debug Mode
test.caller() calling test.methodMonitored()!

在Debug Mode下,数据库连接类只需记录特定函数的最后一次调用者,从而在某个对象占用超时的时候使用该信息。


其实这种方法也可以限制某方法的调用者只能为给定的类或其方法等,这可以实现C++里面类似友元函数的功能。

将异常(getStackTrace)转化成String

将异常(getStackTrace)转化成String

slf4j如何打印java异常堆栈信息throwable对象

slf4j如何打印java异常堆栈信息throwable对象

获得java.lang.Throwable错误堆栈信息

在java语言中java.lang.Throwable是所有error、exceptiond

Android Studio 屏幕分辨率适配

android studio进行android 应用屏幕分辨率适配使用建立不同dimens.xml方法,刚开始建立的文件夹都叫 values-1280x720 values-800x400之类的,发现...

Android从右到左布局(RTL Layout)

从Android 4.2开始,Android SDK支持一种从右到左(RTL,Right-to-Left)UI布局的方式,尽管这种布局方式经常被使用在诸如阿拉伯语、希伯来语等环境中,中国用户很少使用。...

得到当前堆栈信息的两种方式(Thread和Throwable)的方法

Thread.currentThread().getStackTrace()[2].getClassName(); 为什么是2 不是1.

使用dbghelp获取调用堆栈--release下的调试方法学

当软件作为release模式被发布给用户时,当程序崩溃时我们很难去查找原因。常见的手法是输出LOG文件,根据LOG文件分析程序崩溃时的运行情况。我们可以通过SEH来捕获程序错误,然后输出一些有用的信息...
  • weiqubo
  • weiqubo
  • 2012年02月14日 22:53
  • 1695

使用dbghelp获取调用堆栈–release下的调试方法学

Author : Kevin Lynx当软件作为release模式被发布给用户时,当程序崩溃时我们很难去查找原因。常见的手法是输出LOG文件,根据LOG文件分析程序崩溃时的运行情况。我们可以通过SEH...

使用dbghelp获取调用堆栈--release下的调试方法学

当软件作为release模式被发布给用户时,当程序崩溃时我们很难去查找原因。常见的手法是输出LOG文件,根据LOG文件分析 程序崩溃时的运行情况。我们可以通过SEH来捕获程序错误,然后输出一些有用的...

使用dbghelp获取调用堆栈--release下的调试方法学(精华)

使用dbghelp获取调用堆栈--release下的调试方法学 Author : Kevin Lynx 当软件作为release模式被发布给用户时,当程序崩溃时我们很难去查找原因。常见的手...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Throwable的使用--取得方法的调用堆栈
举报原因:
原因补充:

(最多只允许输入30个字)