0x002-第2讲-Exception和Error有什么区别?

/ Java / 0 条评论 / 990浏览

本期话题:聊聊Java的异常吧,Exception和Error?运行时异常与一般异常?

General Knowledge or Common Sense

Throwable、Exception、Error的设计和分类 + 自定义异常

异常类图

小作业:NoClassDefFoundError vs ClassNotFoundException

JVM或者ClassLoader在加载一个class(通过方法调用或者创建实例)的时候,目标class没有被找到。编译期间可以被编译,但是运行时找不到。可能的原因,比如OSGI文件里的lib包,没有在导出插件时被一起导出。

/**
 * Thrown if the Java Virtual Machine or a <code>ClassLoader</code> instance
 * tries to load in the definition of a class (as part of a normal method call
 * or as part of creating a new instance using the <code>new</code> expression)
 * and no definition of the class could be found.
 * <p>
 * The searched-for class definition existed when the currently
 * executing class was compiled, but the definition can no longer be
 * found.
 *
 * @author  unascribed
 * @since   JDK1.0
 */

通过Class.ForName或者ClassLoader.findSystemClass、CLassLoader.loadClass通过类的QualifiedName加载失败,常见于XML文件注册注入类对象时发生

/**
 * Thrown when an application tries to load in a class through its
 * string name using:
 * <ul>
 * <li>The <code>forName</code> method in class <code>Class</code>.
 * <li>The <code>findSystemClass</code> method in class
 *     <code>ClassLoader</code> .
 * <li>The <code>loadClass</code> method in class <code>ClassLoader</code>.
 * </ul>
 * <p>
 * but no definition for the class with the specified name could be found.
 *
 * <p>As of release 1.4, this exception has been retrofitted to conform to
 * the general purpose exception-chaining mechanism.  The "optional exception
 * that was raised while loading the class" that may be provided at
 * construction time and accessed via the {@link #getException()} method is
 * now known as the <i>cause</i>, and may be accessed via the {@link
 * Throwable#getCause()} method, as well as the aforementioned "legacy method."
 *
 * @author  unascribed
 * @see     java.lang.Class#forName(java.lang.String)
 * @see     java.lang.ClassLoader#findSystemClass(java.lang.String)
 * @see     java.lang.ClassLoader#loadClass(java.lang.String, boolean)
 * @since   JDK1.0
 */

How to use code handle Exception?

//扩展了AotuCloseable或者Closeable的对象
try (BufferedReader br = new BufferedReader(…);
     BufferedWriter writer = new BufferedWriter(…)) {// Try-with-resources
// do something
catch ( IOException | XEception e) {// Multiple catch
   // Handle it
} 

Something important

性能为王

延展小话题:异常的日志

分布式环境下出现异常后,如果快速定位问题呢。一般通过ELK可以搭建日志平台,收集日志。增加traceid/requestId也可以串联 多线程日志:通过MDC/NDC功能串联日志,或者traceid和requestid

抛一个问题:Checked Exception对Lambda/Stream造成的麻烦(目前体会尚欠,后续更新) lambda的程序,调用一个抛出检查异常的方法,现在语言层面并没有流畅处理机制,往往需要自定义functional interface 再抛一个问题:Reactive Stream对异常处理的最佳实践(目前体会尚欠,后续更新)

Checked Exception 不兼容 functional 编程,如果你写过 Lambda/Stream 代码,相信深有体会。

1.异常:这种情况下的异常,可以通过完善任务重试机制,当执行异常时,保存当前任务信息加入重试队列。重试的策略根据业务需要决定,当达到重试上限依然无法成功,记录任务执行失败,同时发出告警。 2.日志:类比消息中间件,处在不同线程之间的同一任务,简单高效一点的做法可能是用traceId/requestId串联。有些日志系统本身支持MDC/NDC功能,可以串联相关联的日志。

准备做的内容:全局异常Spring MVC,后续更新文章和代码到github

参考文档: