捕获到异常时,往往需要进行一些处理。比较简单直接的方式就是打印异常栈轨迹Stack Trace。说起栈轨迹,可能很多人和我一样,第一反应就是printStackTrace()方法。其实除了这个方法,还有一些别的内容也是和栈轨迹有关的。

1.printStackTrace()

首先需要明确,这个方法并不是来自于Exception类。Exception类本身除了定义了几个构造器之外,所有的方法都是从其父类继承过来的。而和异常相关的方法都是从java.lang.Throwable类继承过来的。而printStackTrace()就是其中一个。

这个方法会将Throwable对象的栈轨迹信息打印到标准错误输出流上。输出的大体样子如下:

1
2
3
4
java.lang.NullPointerException
         at MyClass.mash(MyClass.java:9)
         at MyClass.crunch(MyClass.java:6)
         at MyClass.main(MyClass.java:3)

输出的第一行是toString()方法的输出,后面几行的内容都是之前通过fillInStackTrace()方法保存的内容。关于这个方法,我们后面会讲。

下面看一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class TestPrintStackTrace {
    public static void f() throws Exception{
        throw new Exception("出问题啦!");
    }
    public static void g() throws Exception{
        f();
    }
    public static void main(String[] args) {
        try {
            g();
        }catch(Exception e) {
            e.printStackTrace();
        }
    }
}

这个例子的输出如下:

1
2
3
4
java.lang.Exception: 出问题啦!
    at TestPrintStackTrace.f(TestPrintStackTrace.java:3)
    at TestPrintStackTrace.g(TestPrintStackTrace.java:6)
    at TestPrintStackTrace.main(TestPrintStackTrace.java:10)

在这个例子中,在方法f()中抛出异常,方法g()中调用方法f(),在main方法中捕获异常,并且打印栈轨迹信息。因此,输出依次展示了f—>g—>main的过程。

2.getStackTrace()方法

这个方法提供了对printStackTrace()方法所打印信息的编程访问。它会返回一个栈轨迹元素的数组。以上面的输出为例,输出的第2-4行每一行的内容对应一个栈轨迹元素。将这些栈轨迹元素保存在一个数组中。每个元素对应栈的一个栈帧。数组的第一个元素保存的是栈顶元素,也就是上面的f。最后一个元素保存的栈底元素。

下面是一个使用getStackTrace()访问这些轨迹栈元素并打印输出的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class TestPrintStackTrace {
    public static void f() throws Exception{
        throw new Exception("出问题啦!");
    }
    public static void g() throws Exception{
        f();
    }
    public static void main(String[] args) {
        try {
            g();
        }catch(Exception e) {
            e.printStackTrace();
            System.out.println("------------------------------");
            for(StackTraceElement elem : e.getStackTrace()) {
                System.out.println(elem);
            }
        }
    }
}

这样的输出和printStackTrace()的输出基本上是一样的,如下:

1
2
3
4
5
6
7
java.lang.Exception: 出问题啦!
    at TestPrintStackTrace.f(TestPrintStackTrace.java:3)
    at TestPrintStackTrace.g(TestPrintStackTrace.java:6)
    at TestPrintStackTrace.main(TestPrintStackTrace.java:10)
TestPrintStackTrace.f(TestPrintStackTrace.java:3)
TestPrintStackTrace.g(TestPrintStackTrace.java:6)
TestPrintStackTrace.main(TestPrintStackTrace.java:10)

3.fillInStackTrace()

我们在前面也提到了这个方法。要说清楚这个方法,首先要讲一下捕获异常之后重新抛出的问题。在catch代码块中捕获到异常,打印栈轨迹,又重新throw出去。在上一级的方法调用中,再捕获这个异常并且打印出栈轨迹信息。这两个栈轨迹信息会一样吗?我们看一下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class TestPrintStackTrace {
    public static void f() throws Exception{
        throw new Exception("出问题啦!");
    }
    public static void g() throws Exception{
        try {
            f();
        }catch(Exception e) {
            e.printStackTrace();
            throw e;
        }
         
    }
    public static void main(String[] args) {
        try {
            g();
        }catch(Exception e) {
            e.printStackTrace();
        }
    }
}

在main方法中捕获的异常,是在g()方法中抛出的,按理说这两个打印栈轨迹的信息应该不同,第二次打印的信息应该没有关于f的信息。但是事实上,两次打印栈轨迹信息是一样的。输出结果如下:

1
2
3
4
5
6
7
8
java.lang.Exception: 出问题啦!
    at TestPrintStackTrace.f(TestPrintStackTrace.java:3)
    at TestPrintStackTrace.g(TestPrintStackTrace.java:7)
    at TestPrintStackTrace.main(TestPrintStackTrace.java:16)
java.lang.Exception: 出问题啦!
    at TestPrintStackTrace.f(TestPrintStackTrace.java:3)
    at TestPrintStackTrace.g(TestPrintStackTrace.java:7)
    at TestPrintStackTrace.main(TestPrintStackTrace.java:16)

也就是说,捕获到异常又立即抛出,在上级方法调用中再次捕获这个异常,打印的栈轨迹信息是一样的。原因在于没有将当前线程当前状态下的轨迹栈的状态保存进Throwabe中。现在我们引入fillInStackTrace()方法。这个方法刚好做的就是这样的保存工作。我们看一下这个方法的原型:

1
public Throwable fillInStackTrace()

这个方法是有返回值的。返回的是保存了当前栈轨迹信息的Throwable对象。我们看看使用fillInStackTrace()方法处理后,打印的栈轨迹信息有什么不同,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class TestPrintStackTrace {
    public static void f() throws Exception{
        throw new Exception("出问题啦!");
    }
    public static void g() throws Exception{
        try {
            f();
        }catch(Exception e) {
            e.printStackTrace();
            //不要忘了强制类型转换
            throw (Exception)e.fillInStackTrace();
        }
         
    }
    public static void main(String[] args) {
        try {
            g();
        }catch(Exception e) {
            e.printStackTrace();
        }
    }
}

输出如下:

1
2
3
4
5
6
7
java.lang.Exception: 出问题啦!
    at TestPrintStackTrace.f(TestPrintStackTrace.java:3)
    at TestPrintStackTrace.g(TestPrintStackTrace.java:7)
    at TestPrintStackTrace.main(TestPrintStackTrace.java:17)
java.lang.Exception: 出问题啦!
    at TestPrintStackTrace.g(TestPrintStackTrace.java:11)
    at TestPrintStackTrace.main(TestPrintStackTrace.java:17)

我们看到,在main方法中打印栈轨迹已经没有了f相关的信息了。

以上就是关于Java栈轨迹的一些我之前没有掌握的内容,记下来备忘。

from: http://www.cnblogs.com/wawlian/archive/2012/06/06/2537844.html

Java异常的栈轨迹(Stack Trace)相关推荐

  1. 第十六章:开发工具-traceback:异常和栈轨迹-底层异常API

    16.5.4 底层异常API 处理异常报告的另一种方法是利用print_exc().这种方法使用sys.exc_info()得到当前线程的异常信息,格式化这个结构,并把文本输出到一个文件句柄(默认为s ...

  2. java异常分析;剖析printStackTrace和fillInStackTrace

    Java异常的栈轨迹(Stack Trace) 捕获到异常时,往往需要进行一些处理.比较简单直接的方式就是打印异常栈轨迹Stack Trace.说起栈轨迹,可能很多人和我一样,第一反应就是printS ...

  3. java异常不懂,看不懂的异常提示啊

    当前位置:我的异常网» Java Web开发 » 看不懂的异常提示啊 看不懂的异常提示啊 www.myexceptions.net  网友分享于:2013-09-12  浏览:7次 看不懂的错误提示啊 ...

  4. Stack Trace

    1.简介 堆栈轨迹(stack trace)是一个方法调用过程的列表,它包含了程序执行过程中方法调用的特定位置. 2.代码 import java.util.Scanner;public class ...

  5. Java中的异常栈轨迹和异常链

    Java中允许对异常进行再次抛出,以提交给上一层进行处理,最为明显的例子为Java的常规异常. 常规异常:有Java所定义的异常,不需要异常声明,在未被try-catch的情况下,会被默认上报到mai ...

  6. 简单看java异常栈

    (stack trace)异常栈轨迹是指: 当 throw Throwable 时, Throwable对象抛出过程(穿梭)所经历的多个方法调用层(方法调用栈).越接近 throw 语句的方法先进入异 ...

  7. jstack命令(Java Stack Trace)

    JDK内置工具使用 一.javah命令(C Header and Stub File Generator) 二.jps命令(Java Virtual Machine Process Status To ...

  8. DEBUG STACK TRACE for PoolBackedDataSource.close() 异常

    今天写项目报错: java.lang.Exception: DEBUG STACK TRACE for PoolBackedDataSource.close() 异常 原因: 配置数据源时加了dest ...

  9. 【异常】Container exited with a non-zero exit code 1 Failing this attempt.Stack trace: ExitCodeException

    [异常]Container exited with a non-zero exit code 1 Failing this attempt.Stack trace: ExitCodeException ...

最新文章

  1. problem-solving-with-algorithms-and-data-structure-usingpython(使用python解决算法和数据结构) -- 基本数据结构(二)...
  2. CVPR2020:点云分类的自动放大框架:PointAugment
  3. java通过反射,泛型将定义的对象与对象之间互转
  4. 笔记-项目范围管理-指导与管理项目工作-控制质量-确认范围-结束项目或阶段...
  5. 线程函数的设计以及MsgWaitForMultipleObjects函数的使用要点
  6. yiicms php版本,yiicms
  7. 黑苹果关机重启后蓝牙连接不上_手机要关机吗,要贴膜吗,要套壳吗?看完这条,都有答案了_政务_澎湃新闻...
  8. kaggle实战—泰坦尼克(三、数据重构)
  9. bitcoin 论文 Introduction
  10. SQL Server中的查询优化技术:基础
  11. Julia : 如何生成一个水仙花数?
  12. SaaSpace:12种最好的免费甘特图软件工具
  13. 正态分布的极大似然估计
  14. 联想G480 i3 2348M扩展内存
  15. [精简]托福核心词汇102
  16. 2018年计算机网络统考考试试题,2018年下半年网络工程师考试上午试题及答案
  17. requests库爬取百度首页
  18. 送书 | 《Django项目开发实战》
  19. 红米5plus刷android one,手机知识:红米5plus如何 红米5plus配置参数
  20. 计算机怎么关屏幕,电脑双屏怎么关闭一个显示器 电脑关闭双屏的具体步骤

热门文章

  1. 编码与乱码(05)---GBK与UTF-8之间的转换--转载
  2. j2ee安全介绍--转
  3. 从weblogic的一个教训
  4. 重庆市推进组建区块链数字资产交易所
  5. 机器学习之多变量线性回归(Linear Regression with multiple variables)
  6. 深入理解分布式技术 - 构建高可用的消息队列
  7. 深入理解分布式技术 - 配置中心
  8. Redis进阶-5.x 单节点 及Redis Cluster 3主3从集群部署
  9. Android开发实用工具汇总-持续更新
  10. 用了虚拟机Linux不能上网,虚拟机Linux不能上网怎么办