您现在的位置是:首页 > 正文

神奇的 new Exception()

2024-01-30 19:54:04阅读 0

先看下一段代码:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        test1();
    }

    private void test1() {
        test2();
    }

    private void test2() {
        test3();
    }

    private void test3() {
        test4();
    }

    private void test4() {
        Log.d("wxl", "test", new Exception());
    }
}

你们猜会打印什么?

12-29 12:16:05.479 8140-8140/com.wuxiaolong.myapplication D/wxl: test
    java.lang.Exception
        at com.wuxiaolong.myapplication.MainActivity.test4(MainActivity.java:29)
        at com.wuxiaolong.myapplication.MainActivity.test3(MainActivity.java:25)
        at com.wuxiaolong.myapplication.MainActivity.test2(MainActivity.java:21)
        at com.wuxiaolong.myapplication.MainActivity.test1(MainActivity.java:17)
        at com.wuxiaolong.myapplication.MainActivity.onCreate(MainActivity.java:13)
        at android.app.Activity.performCreate(Activity.java:6975)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1213)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2770)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)
        at android.app.ActivityThread.-wrap11(Unknown Source:0)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)
        at android.os.Handler.dispatchMessage(Handler.java:105)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6541)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

是不是有点神奇,居然把 test4() 方法调用关系给打印出来了,是怎么做到的?是不是有地方把这个每步调用关系给保存下来了。

首先进 Log 看下 Log.d():

public static int d(String tag, String msg, Throwable tr) {
    return println(LOG_ID_MAIN, DEBUG, tag, msg + '\n' + getStackTraceString(tr));
}

public static String getStackTraceString(Throwable tr) {
    if (tr == null) {
        return "";
    }
    // This is to reduce the amount of log spew that apps do in the non-error
    // condition of the network being unavailable.
    Throwable t = tr;
    while (t != null) {
        if (t instanceof UnknownHostException) {
            return "";
        }
        t = t.getCause();
    }
    StringWriter sw = new StringWriter();
    PrintWriter pw = new PrintWriter(sw);
    tr.printStackTrace(pw);
    pw.flush();
    return sw.toString();
}

这里第三个参数 Exception 是 Throwable 子类,初始化看 Throwable 构造方法:

public Throwable(String message) {
    fillInStackTrace();
    detailMessage = message;
}

/**
 * Fills in the execution stack trace. This method records within this
 * {@code Throwable} object information about the current state of
 * the stack frames for the current thread.
 *
 * <p>If the stack trace of this {@code Throwable} {@linkplain
 * Throwable#Throwable(String, Throwable, boolean, boolean) is not
 * writable}, calling this method has no effect.
 *
 * @return  a reference to this {@code Throwable} instance.
 * @see     java.lang.Throwable#printStackTrace()
 */
public synchronized Throwable fillInStackTrace() {
    if (stackTrace != null ||
        backtrace != null /* Out of protocol state */ ) {
        backtrace = nativeFillInStackTrace();
        stackTrace = libcore.util.EmptyArray.STACK_TRACE_ELEMENT;
    }
    return this;
}

如自己所想,这里 fillInStackTrace() ,正是一步一步地追踪方法的调用,直到追踪到线程的终端。fillInStackTrace 是 native 方法,就不往下​跟了。​

Exception 表示可以被程序捕获并处理的异常错误,JVM 用方法调用栈来跟踪每个线程中一系列的方法调用过程,该栈保存了每个调用方法的本地信息。

对于独立的 Java 程序,可以一直到该程序的 main 方法,当一个新方法被调用的时候,JVM 把描述该方法的栈结构置入栈顶,位于栈顶的方法为正确执行的方法,当一个 Java 方法正常执行完毕,JVM 会从调用栈中弹处该方法的栈结构,然后继续处理前一个方法,如果 java 方法在执行代码的过程中抛出异常,JVM 必须找到能捕获异常的 catch 块代码,它首先查看当前方法是否存在这样的 catch 代码块,如果存在就执行该 catch 代码块,否则 JVM 回调用栈中弹处该方法的栈结构,继续到前一个方法中查找合适的 catch 代码块,最后如果 JVM 向上追到了 main()方法,也就是一直把异常抛给了 main()方法,仍然没有找到该异常处理的代码块,该线程就会异常终止,如果该线程是主线程,应用程序也随之终止,此时 JVM 将把异常直接抛给用户,在用户终端上会看到原始的异常信息。

我的公众号:吴小龙同学,欢迎关注交流,公号回复关键字「1024」有惊喜哦。

网站文章

  • 高并发数据的重复写入问题

    高并发数据的重复写入问题使用Redis的setnx来解决这个问题。setnx key value 若 value 存在 则返回 False.def db_op_thread_func(i, num_o...

    2024-01-30 19:53:57
  • python turtle 做贪吃蛇(原创)(我是个初学者,不太行,敬请谅解)

    在本程序中,蛇是有生命值的、分数的,生命值在15~25条命之间。本程序中每秒10帧,因此Delay=0.1。接下来,初始化开始,包括主角们和配角们;medicineif是决定medicine的是否存在的变量~~~因为在本代码中,内置turtle只是个克隆机,因此隐藏~~~今天,咱用Python的turtle来做贪吃蛇。......

    2024-01-30 19:53:28
  • 大话主席(superslide和 touchslide)插件的使用

      对于实现效果来说,插件的办事效率真的是太高了,而且里边也被处理过兼容性,用起来实在是特别方便,现在我们来说说大话主席中的slide插件,它分为pc端(superslide)和移动端(touchslide)。 superslide:   1、引用jQuery.js 和 jquery.SuperSlide.js 因为SuperSlide是基于jQuery的插件,所以前提...

    2024-01-30 19:53:19
  • 详解java定时任务 热门推荐

    在我们编程过程中如果需要执行一些简单的定时任务,无须做复杂的控制,我们可以考虑使用JDK中的Timer定时任务来实现。下面LZ就其原理、实例以及Timer缺陷三个方面来解析java Timer定时器。一、简介 在java中一个完整定时任务需要由Timer、TimerTask两个类来配合完成。 API中是这样定义他们的,Timer:一种工具,线程用其安排以后在后台线程中执行的任务。可安排任

    2024-01-30 19:53:11
  • 计算机网络第二章知识点复习

    计算机网络第二章知识点复习缩写HTTP:超文本传输协议 HTML:超文本标记语言 URL:统一资源定位符 RTT:往返时间 FTP:文件传输协议 SMTP:简单邮件传输协议 MIME:多媒体邮件扩展 POP:邮局协议 IMAP:因特网邮件访问协议 DNS:域名系统 TLD:顶级域 DHT:分布式散列表 API:应用程序编程接口 RR:资源记录术语**socket:套接字

    2024-01-30 19:52:41
  • java运算符

    java运算符

    java运算符的相关内容

    2024-01-30 19:52:34
  • 计算机远程桌面多用户连接,电脑远程连接如何打开并设置多用户登录

    计算机远程桌面多用户连接,电脑远程连接如何打开并设置多用户登录

    远程连接功能,对于普通用户来说,应该是用的比较少的功能之一,所以在win7系统上是默认关闭的一个功能,可是有部分用户,在某些时候,可能会用到远程桌面连接功能,那么究竟应该如何打开并设置多用户登录呢?针...

    2024-01-30 19:52:26
  • 库函数的模拟实现

    模拟实现strlen://方法1:计数器方式int my_strlen(const char *str){ int count = 0; assert(str); while (*str) { ++...

    2024-01-30 19:51:58
  • 正则表达式的反向引用

    1、反向引用(Backreferences)是Java正则表达式的重要特性。为了理解反向引用,我们先对解释Java正则表达式里面的组。组在正则表达式中意味着将多个字符作为一个单独的单元,通过将字符放在()中,每个()代表一个组。每一组都有一个行号,从1开始。Matcher类的groupCount方法返回模式(Pattern)关联Matcher实例组的个数。第0组指向整个表达式。2、

    2024-01-30 19:51:41
  • 宁波银行技术面经-2021.8

    宁波银行技术面经-2021.8校园招聘 校园招聘 1、自我介绍 2、创建线程有几种方式 3、抽象类和接口的区别 4、你的技术栈有哪些 5、介绍一个你做过的项目 6、项目中有没有遇到困难,讲一下 7、说...

    2024-01-30 19:51:35