面试----exception和error

运行时异常与一般异常有什么区别?以及exception和error的对比?

 

exception和error

一、相同点:

1.都继承了throwable类,在java中只有继承了该类才可以被抛出并捕获。

二、不同点:

1.exception和error体现了java平台设计者对不同异常情况的分类。exception是程序正常运行中,可以预料的意外情况,可以捕获并进行处理;而error则是正常情况下,不大可能出现的情况,绝大部分的error都会导致程序处于非正常的,不可恢复的状态。既然是非正常状态,则也不需要捕获,常见的如OutOfMemoryError之类。

2.exception分为可检查异常和不可检查异常,可检查异常在源代码中必须显示的进行try-catch。这是编译器检查的一部分,不可检查的比如空指针异常以及类转换异常,越界异常等。

 

如何处理异常

1.捕获异常不可一网打尽:

try{

//业务代码

Thread.sleep(1000L);

}catch(Exception){

//Ignore it

}

第一、尽量不要捕获Exception这样的异常,而是应当捕获特定异常,我们要让我们的代码表现出更多信息。exception这样泛泛而谈的概念会掩盖真实的目的。如果要捕获多个异常,将父类异常放在最后catch,子类异常放在之前catch

第二、不要生吞异常,这样程序在出错后我们不知道可能会很难诊断诡异的情况

 

2.尽量不要将异常打印到堆栈中

try{

//业务代码

}catch(IOException e){

    e.printStachTrace();

}

这段代码在实际产品中不允许这样处理

  e.printStachTrace()不是一个合适的输出选项,因为你很难判断到底输出到哪里去了。尤其是对于分布式系统,如果发生异常,是无法找到堆栈轨迹,这蠢事是为诊断设置障碍,所以最好使用产品日志,详细的输出到日志系统里面。

 

 

自我构建异常

 

1.是否需要定义成checkedException,因为这种类型设计的初衷更是为了从异常情况回复,作为异常设计者,我们往往有足够信息进行分类。

2.在保证诊断信息足够的同时,也要考虑避免敏感信息,因为这样会导致潜在的安全问题。比如java.net.ConnectException,出错信息是类似“Connection refused”,而不包含具体的机器名,IP,端口等。一个重要考量就是信息安全。类似情况在日志中也有,比如,用户数据一般是不可输出到日志里面的。

 

异常处理的开销

 

1.try-catch代码会产生额外的性能开销,或者换个角度说,它往往会影响JVM对代码进行优化,所以建议仅捕获有必要的代码段,而不是全部try-catch。同时利用异常控制代码流程也不是一个好主意,远远不如if else高效。

2.java每实例化一个Exception,都是对当时的栈进行快照【1】,这是一个相对比较繁重的操作。如果发生非常频繁,这个开销可就不能被忽略了。

所以对于部分追求极致性能的底层类库,有种方式是尝试创建不进行栈快照的Exception。这本身也存在争议,因为这样做的假设在于,我创建异常时知道未来是否需要堆栈。问题是这样可能吗?在大型项目中,这样做可能不是一个理智的选择。如果需要堆栈,但有没有收集这些信息,在复杂情况下,尤其是类似微服务这种分布式系统,这会大大增加诊断的难度。

当我们的服务出现反应变慢,吞吐量下降的时候,检查最频繁发生的异常也是一种思路,关于诊断后台变慢的问题,后面的java性能基础模块中系统探讨。

 

【1】栈快照

 

 

存储快照

全球网络存储工业协会SNIA(StorageNetworking Industry Association)对快照(Snapshot)的定义是:关于指定数据集合的一个完全可用拷贝,该拷贝包括相应数据在某个时间点(拷贝开始的时间点)的映像。快照可以是其所表示的数据的一个副本,也可以是数据的一个复制品。

快照的作用主要是能够进行在线数据备份与恢复。当存储设备发生应用故障或者文件损坏时可以进行快速的数据恢复,将数据恢复某个可用的时间点的状态。快照的另一个作用是为存储用户提供了另外一个数据访问通道,当原数据进行在线应用处理时,用户可以访问快照数据,还可以利用快照进行测试等工作。所有存储系统,不论高中低端,只要应用于在线系统,那么快照就成为一个不可或缺的功能。 [1] 

快照的实现方式

当前实现快照有主要有两种技术,一种是第一次写时复制(Copy OnFirst Write,COFW),有时简称为写时复制(CopyOn Write,COW)。即在数据第一次写入到某个存储位置时,首先将原有的内容读取出来,写到另一位置处(为快照保留的存储空间,此文中我们称为快照空间),然后再将数据写入到存储设备中。而下次针对这一位置的写操作将不再执行写时复制操作。这种技术常在计算机相关的技术中经常初使用,其基本原理大同小异,只是面向的对象不同,适用的场合不一样。从COW 的执行过程我们可以知道,这种实现方式在第一次写入某个存储位置时需要完成一个读操作(读原位置的数据),两个写操作(写原位置与写快照空间),如果写入频繁,那么这种方式将非常消耗IO时间。因此可推断,如果预计某个卷上的I/O多数以读操作为主,写操作较少,这种方式的快照实现技术是一个较理想的选择,因为快照的完成需要较少的时间。除此之外,如果一个应用易出现写入热点,即只针对某个有限范围内的数据进行写操作,那么COW的快照实现方式也是较理想的选择。因为其数据更改都局限在一个范围内,对同一份数据的多次写操作只会出现一次写时复制操作。

写时复制的示意

下图是写时复制的示意图

写时复制的示意图写时复制的示意图

:但是这种方式的缺点也是非常明显的。如果写操作过于分散且频繁,那么 COW造成的开销则是不可忽略的,有时甚至是无法接受的。因此在应用时,则需要综合评估应用系统的使用场景,以判断这种方式的快照是否适用。快照实现技术中的另一种技术是 I/O 重定向(I/O Redirect)。即将读写操作重新定向到另一个存储空间中。在一个快照生成期间,所有的写操作将被重定向到另一个介质,而读操作是否需要读重定向,则需要根据读取的位置是否有过自上次快照以来的写重定向,必须对有过写重定向的位置进行读重定向,否则不需要进行读定向。当要创建一个快照时,则将自上次快照以来所有的重定向写数据所对应在源介质中的数据复制出来生成这个时间点的快照,然后再将这些重定向写数据写回到源介质中的相应位置上,从而完成一个快照生成过程。

I/O 重定向示意

下图中显示了IO重定向的执行过程。

I/O 重定向示意图I/O 重定向示意图

从上面的过程来看,关键的性能影响在于快照生成时的四次I/O操作(一次读源介质,一次写快照数据,一次读快照介质,一次写源介质),另一个则是重定向的计算工作。这种方式虽然看起来最后生成快照时的I/O操作较多,但是考虑到这个操作是在生成快照时才会发生,特别是快照生成时可以对I/O操作进行排序,可以使得对介质的读写得到较好的优化,因此使影响很小。而对于重定向的计算操作对于当下的计算能力来说,不会成为一个性能的瓶颈问题。因此这种快照实现方式在非快照执行期间的影响甚小。因此这种方式比较适合Write-Intensive(写密集)类型的存储系统

快照生成

下图是快照生成过程的示意图:SNIA 将快照的实现方式表述为:镜像分离(split mirror)、改变块(changed block)、并发(concurrent)三大类。后两种在实现时其实质就是写时复制及I/O重定向。对于 split mirror的方式,由于其灵活性以及开销问题,在实际的存储系统中,并不实用。

实现层次

编辑

概述

计算机的存储结构是一个类似于 TCP/IP 一样的栈结构。栈中包括硬件与软件部分。栈中不同层为上层提供服务,同时利用下层的接口(如下图)。

存储栈存储栈

存储栈

因此在实现上,快照可以在不同的栈层上实现。但是不同的层其效果及特点是不一样的。一般来说,在应用层不太合适实现快照功能。因为不同的应用是千差万别的,因此需要针对不同的应用实现快照功能,这个代价也太高了。但在应用层实现快照也并不是说一无用处,如在应用层实现快照的一个典型的例子就是 vmWare 虚拟化软件中的快照功能。只是这种快照功能应用在存储系统中不现实。其次在文件系统层实现快照与应用也是具有同样的缺点,就是需要针对不同的文件系统实现快照功能,这样的代价也很大。

实现层次案例

实现的快照的功能的文件系统基本上都是一些专用系统或者专为某个特定功能实现的文件系统。在这个层级上实现快照,缺乏灵活性和可扩展性。这个比较典型的例子就是ZFS。而较为适宜实现快照功能的层应该为卷管理层以及物理层。在这两个层中都不与特定的应用及文件系统相关。这里比较典型的例子有Linux 的LVM。而在硬件层次上实现快照又通常有许多种,在这个层次上实现的快照一般为专用系统,好处是性能是各个方式中最好的。但是在这个层次上实现的快照也有一个不可避免的缺点,那就是由于不与特定的应用及文件系统关联,因此其就无法理解上层的应用逻辑,也就无法保证每个快照都处于数据一致性状态的。但是这个缺点是可以通过其他的方式减少或者解决的,比如在生成快照之前先对数据进行刷新操作,或者在恢复快照时对文件系统进行一致性检查等。结束语计算技术不断在进步,存储技术同样也在进行着日新月异的变化。不同的应用在不断地更新着对存储的需求。同时对于数据重要性的体现,各种容灾技术也给用户的数据加上了防护安全帽。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章