从源码角度分析Android系统的异常捕获机制是如何运行的

我们在开发的时候经常会遇到各种异常,当程序遇到异常,便会将异常信息抛到LogCat中,那这个过程是怎么实现的呢?


我们以一个例子开始:

import android.app.Activity;
import android.os.Bundle;public class MainActivity4 extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);throw new NullPointerException();}
}

这个程序一启动便会抛一个异常到Logcat中,就像这样:

10-10 16:44:16.200: W/dalvikvm(381): threadid=1: thread exiting with uncaught exception (group=0x41588d58)
10-10 16:44:16.200: W/System.err(381): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.sahadev.renren/com.sahadev.activitythemetest.MainActivity4}: java.lang.NullPointerException
10-10 16:44:16.200: W/System.err(381): 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2263)
10-10 16:44:16.200: W/System.err(381): 	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2313)
10-10 16:44:16.200: W/System.err(381): 	at android.app.ActivityThread.access$800(ActivityThread.java:147)
10-10 16:44:16.200: W/System.err(381): 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1226)
10-10 16:44:16.200: W/System.err(381): 	at android.os.Handler.dispatchMessage(Handler.java:102)
10-10 16:44:16.200: W/System.err(381): 	at android.os.Looper.loop(Looper.java:136)
10-10 16:44:16.200: W/System.err(381): 	at android.app.ActivityThread.main(ActivityThread.java:5137)
10-10 16:44:16.200: W/System.err(381): 	at java.lang.reflect.Method.invokeNative(Native Method)
10-10 16:44:16.200: W/System.err(381): 	at java.lang.reflect.Method.invoke(Method.java:515)
10-10 16:44:16.200: W/System.err(381): 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:801)
10-10 16:44:16.200: W/System.err(381): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:617)
10-10 16:44:16.200: W/System.err(381): 	at dalvik.system.NativeStart.main(Native Method)
10-10 16:44:16.200: W/System.err(381): Caused by: java.lang.NullPointerException
10-10 16:44:16.200: W/System.err(381): 	at com.sahadev.activitythemetest.MainActivity4.onCreate(MainActivity4.java:12)
10-10 16:44:16.200: W/System.err(381): 	at android.app.Activity.performCreate(Activity.java:5231)
10-10 16:44:16.200: W/System.err(381): 	at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
10-10 16:44:16.200: W/System.err(381): 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2227)
10-10 16:44:16.200: W/System.err(381): 	... 11 more

好,异常信息就会通过Logcat输出出来,接下来我们一起看一下它内部的工作原理:

首先:

我们知道通常我们在处理全局自定义异常的时候通常会这么写:

import java.lang.Thread.UncaughtExceptionHandler;public class YikaoGlobalCrashHandler implements UncaughtExceptionHandler {public YikaoGlobalCrashHandler() {super();Thread.setDefaultUncaughtExceptionHandler(this);}@Overridepublic void uncaughtException(Thread thread, Throwable ex) {}
}
通过这样的方式,我们便可以使程序在遇到异常的时候回调我们的对象实例,然后调用我们的uncaughtException方法。
 

我们知道,如果我们不这么设定,系统是会自己处理异常的,那就一定有一个默认的异常处理对象,没错:

Thread.getDefaultUncaughtExceptionHandler();
通过这个方法会返回一个系统默认的UncaughtExceptionHandler对象,那么这个对象是在哪被设置进去的呢?我们从源代码里面找答案:

咱们从Java最基础层面看起,

我们的JAVA入口是:com.android.internal.os.RuntimeInit类的main方法,至于main方法在哪被调用,我们以后再讨论:

 public static final void main(String[] argv) {if (argv.length == 2 && argv[1].equals("application")) {if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application");redirectLogStreams();} else {if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting tool");}commonInit();/** Now that we're running in interpreted code, call back into native code* to run the system.*/nativeFinishInit();if (DEBUG) Slog.d(TAG, "Leaving RuntimeInit!");}

我们关注的是commonInit方法:

    private static final void commonInit() {if (DEBUG) Slog.d(TAG, "Entered RuntimeInit!");/* set default handler; this applies to all threads in the VM */Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler());/** Install a TimezoneGetter subclass for ZoneInfo.db*/TimezoneGetter.setInstance(new TimezoneGetter() {@Overridepublic String getId() {return SystemProperties.get("persist.sys.timezone");}});TimeZone.setDefault(null);/** Sets handler for java.util.logging to use Android log facilities.* The odd "new instance-and-then-throw-away" is a mirror of how* the "java.util.logging.config.class" system property works. We* can't use the system property here since the logger has almost* certainly already been initialized.*/LogManager.getLogManager().reset();new AndroidConfig();/** Sets the default HTTP User-Agent used by HttpURLConnection.*/String userAgent = getDefaultUserAgent();System.setProperty("http.agent", userAgent);/** Wire socket tagging to traffic stats.*/NetworkManagementSocketTagger.install();/** If we're running in an emulator launched with "-trace", put the* VM into emulator trace profiling mode so that the user can hit* F9/F10 at any time to capture traces.  This has performance* consequences, so it's not something you want to do always.*/String trace = SystemProperties.get("ro.kernel.android.tracing");if (trace.equals("1")) {Slog.i(TAG, "NOTE: emulator trace profiling enabled");Debug.enableEmulatorTraceOutput();}initialized = true;}

在我们代码的第二行看到:Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler());那这个UncaughtHandler类在哪被定义呢?我们还可以在RuntimeInit.java中找到答案:

    /*** Use this to log a message when a thread exits due to an uncaught* exception.  The framework catches these for the main threads, so* this should only matter for threads created by applications.*/private static class UncaughtHandler implements Thread.UncaughtExceptionHandler {public void uncaughtException(Thread t, Throwable e) {try {// Don't re-enter -- avoid infinite loops if crash-reporting crashes.if (mCrashing) return;mCrashing = true;if (mApplicationObject == null) {Clog_e(TAG, "*** FATAL EXCEPTION IN SYSTEM PROCESS: " + t.getName(), e);} else {StringBuilder message = new StringBuilder();message.append("FATAL EXCEPTION: ").append(t.getName()).append("\n");final String processName = ActivityThread.currentProcessName();if (processName != null) {message.append("Process: ").append(processName).append(", ");}message.append("PID: ").append(Process.myPid());Clog_e(TAG, message.toString(), e);}// Bring up crash dialog, wait for it to be dismissedActivityManagerNative.getDefault().handleApplicationCrash(mApplicationObject, new ApplicationErrorReport.CrashInfo(e));} catch (Throwable t2) {try {Clog_e(TAG, "Error reporting crash", t2);} catch (Throwable t3) {// Even Clog_e() fails!  Oh well.}} finally {// Try everything to make sure this process goes away.Process.killProcess(Process.myPid());System.exit(10);}}}


我们看到代码中使用StringBuilder的message对象对基本信息进行了组合,然后调用Clog_e方法,Clog_e方法通过

Log.println_native(Log.LOG_ID_CRASH, Log.ERROR, tag,msg + '\n' + Log.getStackTraceString(tr));将Log日志输出到控制台。

接下来会调用

 // Bring up crash dialog, wait for it to be dismissedActivityManagerNative.getDefault().handleApplicationCrash(mApplicationObject, new ApplicationErrorReport.CrashInfo(e));
方法将我们的崩溃的Dialog显示出来,就像这样:

最终它还会将我们的程序杀死退出:

 // Try everything to make sure this process goes away.Process.killProcess(Process.myPid());System.exit(10);

好这就是系统为我们提供的默认异常处理方法,接下来当然还有不少疑问:

1.RuntimeInit类的main方法是在哪被调用的。

2.throw new NullPointerException();这部分是怎么执行的。

3.Thread的defaultUncaughtHandler属性又是在哪被调用的。

4.等等


欢迎对这方面有兴趣的可以在评论区参与讨论,也有可能是我学的还太少。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/479556.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

法律规则鬼畜图解||全面易懂的旅游投诉赔偿标准

法律规则鬼畜图解||全面易懂的旅游投诉赔偿标准https://zhuanlan.zhihu.com/p/82878902 执笔人:张宗保律师(联系方式:知乎私信)执业地域:深圳市执业方向:民商事诉讼一、赔偿标准的适用前提只有在旅游者和旅…

美团技术十年:让我们感动的那些人那些事

时光荏苒,美团十岁了,美团技术团队也走过了十个春秋。 2010年3月4日美团网上线的时候,整个公司总共十来人,在一套三居室的民房里起步。其中技术团队只有5个人,现在有4位还在美团。 今天,美团是中国市值第三…

LeetCode 113. 路径总和 II(回溯)

文章目录1. 题目信息2. 解题1. 题目信息 给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。 说明: 叶子节点是指没有子节点的节点。 示例: 给定如下二叉树,以及目标和 sum 22,5/ \4 8/ / \11 1…

开放开源 | DeepKE:基于深度学习的开源中文关系抽取工具

本文转载自公众号:浙大 KG。作者:余海阳机构:浙江大学代码地址: https://github.com/zjunlp/deepkeOpenKG 发布地址: http://openkg.cn/tool/deepke一、系统简介关系抽取是知识图谱构建的基本子任务之一,它主要面向非结构化的文本…

微前端在美团外卖的实践

背景 微前端是一种利用微件拆分来达到工程拆分治理的方案,可以解决工程膨胀、开发维护困难等问题。随着前端业务场景越来越复杂,微前端这个概念最近被提起得越来越多,业界也有很多团队开始探索实践并在业务中进行了落地。可以看到&#xff0c…

论文浅尝 | Meta Relational Learning: 基于元关系学习的少样本知识图谱推理

本文转载自公众号:浙大KG。 笔记整理:陈名杨,浙江大学在读博士发表会议:EMNLP-2019论文链接:https://arxiv.org/abs/1909.01515开源代码&…

测试集没标签,可以拿来测模型吗?

文:维建编:白鹡鸰背景正常情况下,我们可以用一个带标签的数据集来测试分类器的表现(称之为测试集)。然而,现实中,因为种种因素的制约(标注成本高、标注难度大等 Google:穷…

从0到1 | 手把手教你如何使用哈工大NLP工具——PyLTP!

原文链接:https://flashgene.com/archives/46041.html 本站内容均来自兴趣收集,如不慎侵害的您的相关权益,请留言告知,我们将尽快删除.谢谢. 作者 | 杨秀璋 来源 | CSDN 博客(CSDN id:Eastmount) 【导语】此文是作者基于 Python 构…

美团智能配送系统的运筹优化实战

深入各个产业已经成为互联网目前的主攻方向,线上和线下存在大量复杂的业务约束和多种多样的决策变量,为运筹优化技术提供了用武之地。作为美团智能配送系统最核心的技术之一,运筹优化是如何在美团各种业务场景中进行落地的呢?本文…

Android如何给无法更改继承关系的Activity更换ActionBar(setContentView方法实战)

前言: 通常我们有时候会直接使用ADT工具直接新建一个Activity页,而这个Activity我们又无法更改它的父类,那遇到这种情况该如何处理呢?其实很简单,好,看如何来解决这个问题: 先来看看这个问题出…

论文浅尝 | 基于属性embeddings的跨图谱实体对齐

论文笔记整理:谭亦鸣,东南大学博士生,研究方向为知识库问答。来源:AAAI 2019链接:https://aaai.org/ojs/index.php/AAAI/article/view/3798跨图谱实体对齐任务的目标是从两个不同知识图谱中找出同一 real-world 实体&a…

LeetCode 771. 宝石与石头(哈希)

文章目录1. 题目信息2. 解题1. 题目信息 给定字符串J 代表石头中宝石的类型,和字符串 S代表你拥有的石头。 S 中每个字符代表了一种你拥有的石头的类型,你想知道你拥有的石头中有多少是宝石。 J 中的字母不重复,J 和 S中的所有字符都是字母…

开启NLP新时代的BERT模型,真的好上手吗?

都说BERT模型开启了NLP的新时代,更有“BERT在手,天下我有”的传说,它解决了很多NLP的难题:1、BERT让低成本地训练超大规模语料成为可能;2、BERT能够联合神经网络所有层中的上下文来进行训练,实现更精准的文…

YOLO系列:YOLOv1,YOLOv2,YOLOv3,YOLOv4,YOLOv5简介

原文链接: https://zhuanlan.zhihu.com/p/136382095 YOLO系列:YOLOv1,YOLOv2,YOLOv3,YOLOv4,YOLOv5简介YOLO系列是基于深度学习的回归方法。RCNN, Fast-RCNN,Faster-RCNN是基于深度学习的分类方法。YOLO官网:https://g…

一站式机器学习平台建设实践

本文根据美团配送资深技术专家郑艳伟在2019 SACC(中国系统架构师大会)上的演讲内容整理而成,主要介绍了美团配送技术团队在建设一站式机器学习平台过程中的经验总结和探索,希望对从事此领域的同学有所帮助。 0. 写在前面 AI是目前…

LeetCode 535. TinyURL 的加密与解密(哈希)

文章目录1. 题目信息2. 哈希解题1. 题目信息 TinyURL是一种URL简化服务, 比如:当你输入一个URL https://leetcode.com/problems/design-tinyurl 时,它将返回一个简化的URL http://tinyurl.com/4e9iAk. 要求:设计一个 TinyURL 的…

论文浅尝 | Doc2EDAG:一种针对中文金融事件抽取的端到端文档级框架

论文笔记整理:叶宏彬,浙江大学博士生,研究方向为知识图谱、自然语言处理。链接:https://arxiv.org/pdf/1904.07535.pdf背景大多数现有的事件提取(EE)方法仅提取句子范围内的事件参数。但是,此类…

NeurIPS'20 | 通过文本压缩,让BERT支持长文本

作者 | wangThr来源 | 知乎这是今年清华大学及阿里巴巴发表在NIPS 2020上的一篇论文《CogLTX: Applying BERT to Long Texts》,介绍了如何优雅地使用bert处理长文本。作者同时开源了不同NLP任务下使用COGLTX的代码:论文题目:CogLTX: Applying…

福利!Android官方网站出现中文版本!

这两天在Android开发者网站上查东西的时候发现有中文的搜索结果,点开结果全是中文的,以后可以畅通无阻的看文档了,快来围观。

自然场景人脸检测技术实践

一、 背景 人脸检测技术是通过人工智能分析的方法自动返回图片中的人脸坐标位置和尺寸大小,是人脸智能分析应用的核心组成部分,具有广泛的学术研究价值和业务应用价值,比如人脸识别、人脸属性分析(年龄估计、性别识别、颜值打分和…