Java异常处理机制

世界上并不存在不会出错的系统,只要是软件系统就一定会在运行的过程中出现开发人员无法预料的错误。如何处理意外发生就是我们作为一名开发人员所必须深入思考的问题。

Java语言提供了完善的异常处理机制,它有效的降低了编写以及维护的门槛(这也是Java语言大行其道的原因,好上手,机制全)。今天在这里和大家分享一下Java异常机制的特点以及应用。

现在我们回想一下,在日常开发中我们常常用到try……catch……语句,比如写一个文件输入输出流,此时我们必须catch相应的IOException、FileNotFountException,否则编译不通过,这里catch的是什么东西?答案是“Exception”。平时我们在系统运行中发现系统崩溃,比如OutOfMemoryError错误,这个OOM是什么东西?答案是“Error”。综上所述,Java中的异常分为两大类,Exception和Error,它们都继承了Throwable类(只有集成了Throwable类才能被抛出或者捕获)。

一、Exception与Error

Error是指正常情况下不大可能出现的情况,一旦出现很有可能导致程序处于不可恢复的非正常状态,开发人员不便于也不需要捕获。Exception则可以分为checked和unchecked异常,checked表示必须显示捕获处理,否则编译不通过。

Object Object
Throwable Throwable
Error Exception
LinkageError、VirtualMachineError unchecked、checked
NoClassDefFoundError和ClassNotFoundException有什么区别?

NoClassDefFoundError是一个错误(Error),而ClassNotFoundException是一个异常(Exception),我们应该尝试从异常中恢复程序,而不应该尝试从错误中恢复程序。

ClassNotFoundException

ClassNotFoundException是一个checkedException,需要显示捕获处理。
ClassNotFoundException产生的原因是:Java使用Class.forName方法动态加载类到JVM内存中,但是如果传递的类在类路径中没有被找到,那么就会抛出ClassNotFoundException异常。ClassLoader.loadClass,ClassLoader.findSystemClass等方法在动态加载类到内存中的时候也可能会跑出去这个异常。
还有一种导致ClassNotFoundException发生的原因,当一个类已经被某个类加载器加载到内存中了,此时另一个类加载器又尝试动态从同一个包中加载这个类。此时也会出现ClassNotFoundException异常。
Demo:

public class Example {

    public static void main(String args[]) {
        try
        {
            Class.forName("GeeksForGeeks");
        }
        catch (ClassNotFoundException ex)
        {
            ex.printStackTrace();
        }
    }
}
NoClassDefFoundError

NoClassDefFoundError产生的原因是:JVM或者ClassLoader实例尝试加载类的时候找不到类的定义。它是一个LlinkageError,LinkageError发生的情况是在一个类依赖另一个类,而后者在前者编译后又发生了改变。导致出现LinkageError的错误。
Demo:

class GeeksForGeeks  
{
    void greeting()
    {
        System.out.println("hello!");
    }
}
class G4G {
    public static void main(String args[])  
    {
        GeeksForGeeks geeks = new GeeksForGeeks();
        geeks.greeting();
    }
}

分别使用javac编译两个文件,然后使用java G4G运行。当我们把编译后的GeeksForGeeks.class文件拿走后,就会报NoClassDefFoundError的错误。

二、异常处理原则

通过上面的描述我们理解了Error和Exception之间的区别,接下来我们需要理解Java语言是如何操作Throwable元素。基本的语法包括“try-catch-finally”,“throw”,“throws”,“try-with-resources”等。异常处理有几个原则需要遵守:
(1)尽量不要捕获类似Exception这样的通用异常,而应该捕获特定异常。
(2)不要生吞异常。注意不要在生产环境使用e.printStackTrace()打印异常,最好使用产品日志,详细输出到日志系统。
(3)Throw early, catch late。提前把异常抛出来,或者构建新的异常抛出去。这里就涉及到自定义异常,需要确定是否需要自定义checked Exception;在保证诊断信息的同事避免敏感信息,比如java.net.ConnectException的出错信息不包括机器名、IP、端口等敏感信息(日志信息也一样,不可以输出用户信息之类的敏感信息)。

有一种说法,提出Java语言的checkedException是一种设计错误。因为checkedException的初衷是希望捕获异常,再从异常中回复正常,但是大多数情况不能恢复。另外checkedException不兼容functional编程(函数式编程,后续我会展开来讲函数式编程、命令式编程的区别),比如Lambda/Stream代码(后续会详细讲Lambda的语法以及原理)。但也有一部分人提出,确实有一些异常是可恢复的,比如IO异常、网络异常等。

三、异常处理与性能

处理异常会必然会增加代码量,那么接下来我们从性能的角度来审视Java的异常处理机制。

  • try-catch代码会影响JVM对代码的优化,所以不要用try包裹大段的代码。
  • 不要试图用异常捕获来控制代码流程,比起if/else之类的语句,异常捕获要更加低效。
  • Java实例化Exception都会对当时的栈进行快照,该操作较重。对于追求极致性能的底层类库,创建不进行栈快照的Exception是一种方法。但是这样不利于我们定位问题,特别是在微服务这样的分布式系统,会增加诊断的难度。当服务变慢,吞度量下降时,检查最频繁的Exception是一种思路。

四、总结

通过本章的学习,我们了解了Java异常中的两大类:Exception与Error。另外我们也学习了ClassNotFoundException和NoClassDefFoundError之间的区别。Java异常处理机制是Java语言一大特征,遵循异常处理原则可以有效提高代码可读性以及程序运行的稳定性。深入的掌握Java异常处理机制对我们Debug线上问题也有帮助。

五、后记

回顾问题:

  1. Exception和Error有什么相同点、不通点?
  2. 常见的CheckedException和RuntimeException有哪些?常见的Error有哪些?
  3. NoClassDefFoundError和ClassNotFoundException有什么区别?

延伸问题:

  1. 为什么错误信息打印,不推荐使用e.printStackTrace()?STERR为什么不是个合适的输出项?
  2. 为什么使用try-catch来控制代码流程,比起if-else更加低效?
  3. 如何创建不进行栈快照的Exception?
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,084评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,623评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,450评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,322评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,370评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,274评论 1 300
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,126评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,980评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,414评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,599评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,773评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,470评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,080评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,713评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,852评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,865评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,689评论 2 354

推荐阅读更多精彩内容

  • 2.JAVA异常 异常指不期而至的各种状况,如:文件找不到、网络连接失败、非法参数等。异常是一个事件,它发生在程...
    青城楼主阅读 555评论 0 0
  • 本文部分来自于:代码钢琴家blog address:www.cnblogs.com/lulipro/p/75042...
    八目朱勇铭阅读 1,317评论 0 4
  • 什么是异常? 异常本质上是程序上的错误,错误在我们编写程序的过程中会经常发生,包括编译期间和运行期间的错误。 编译...
    若兮缘阅读 3,356评论 0 11
  • [toc] Java语言在设计之初就提供了相对完善的异常处理机制,大大提高了程序的可靠性。 异常的分类 我们编写的...
    52718阅读 441评论 0 1
  • 异常指不期而至的各种状况,如:文件找不到、网络连接失败、非法参数等。异常是一个事件,它发生在程序运行期间,干扰了正...
    谁吃了我的薯条阅读 238评论 0 0