Java异常处理步骤:
第一句一般是总的,告诉你哪里错了,错误就在caused by后面的语句提示里面,或者是自己写的类里面。异常信息是从上往下抛(大概的说法)的,因为下面是调用上面的方法,也就是说第一行是最终抛出异常的方法,而最后一行最上层调用的方法
异常链是一种机制,异常转译时,保存原来的异常,这样当这个异常再被转译时,还会被保存,于是就成了一条链了,包含了所有的异常,所以你可以看到这样的异常打印:

org.apache.phoenix.exception.PhoenixIOException: org.apache.phoenix.exception.PhoenixIOException: 系统找不到指定的路径。
	at org.apache.phoenix.util.ServerUtil.parseServerException(ServerUtil.java:107)
	at org.apache.phoenix.iterate.ParallelIterators.getIterators(ParallelIterators.java:527)
	at org.apache.phoenix.iterate.MergeSortResultIterator.getIterators(MergeSortResultIterator.java:48)
	at org.apache.phoenix.iterate.MergeSortResultIterator.minIterator(MergeSortResultIterator.java:63)
	at org.apache.phoenix.iterate.MergeSortResultIterator.next(MergeSortResultIterator.java:90)
	at org.apache.phoenix.jdbc.PhoenixResultSet.next(PhoenixResultSet.java:734)
	at com.youku.service.VideoFingerprintServiceNew.getSimlarVideoMD5(VideoFingerprintServiceNew.java:111)
	at com.youku.service.VideoFingerprintServiceNew.excute(VideoFingerprintServiceNew.java:50)
	at com.youku.service.AbstractHttpImpl.getResponseModel(AbstractHttpImpl.java:22)
	at com.youku.web.servlet.CommonHttpServlet.doPost(CommonHttpServlet.java:79)
	at com.youku.web.servlet.CommonHttpServlet.doGet(CommonHttpServlet.java:41)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:723)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:861)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:612)
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:503)
	at java.lang.Thread.run(Thread.java:745)
Caused by: java.util.concurrent.ExecutionException: org.apache.phoenix.exception.PhoenixIOException: 系统找不到指定的路径。
	at java.util.concurrent.FutureTask.report(FutureTask.java:122)
	at java.util.concurrent.FutureTask.get(FutureTask.java:202)
	at org.apache.phoenix.iterate.ParallelIterators.getIterators(ParallelIterators.java:523)
	... 23 more
Caused by: org.apache.phoenix.exception.PhoenixIOException: 系统找不到指定的路径。
	at org.apache.phoenix.util.ServerUtil.parseServerException(ServerUtil.java:107)
	at org.apache.phoenix.iterate.SpoolingResultIterator.(SpoolingResultIterator.java:129)
	at org.apache.phoenix.iterate.SpoolingResultIterator.(SpoolingResultIterator.java:74)
	at org.apache.phoenix.iterate.SpoolingResultIterator$SpoolingResultIteratorFactory.newIterator(SpoolingResultIterator.java:68)
	at org.apache.phoenix.iterate.ChunkedResultIterator.(ChunkedResultIterator.java:90)
	at org.apache.phoenix.iterate.ChunkedResultIterator$ChunkedResultIteratorFactory.newIterator(ChunkedResultIterator.java:70)
	at org.apache.phoenix.iterate.ParallelIterators$2.call(ParallelIterators.java:631)
	at org.apache.phoenix.iterate.ParallelIterators$2.call(ParallelIterators.java:622)
	at java.util.concurrent.FutureTask.run(FutureTask.java:262)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
	... 1 more

这个异常链中就是包含了两个异常,最前面是顶级异常,后面再打印一个Cause by,然后再打印低一层异常,直到打印完所有的异常。
异常链,在JDK1.4以后版本中,Throwable类支持异常链机制。Throwable 包含了其线程创建时线程执行堆栈的快照。它还包含了给出有关错误更多信息的消息字符串。最后,它还可以包含 cause(原因):另一个导致此 throwable 抛出的 throwable。它也称为异常链 设施,因为 cause 自身也会有 cause,依此类推,就形成了异常链,每个异常都是由另一个异常引起的。
通俗的说,异常链就是把原始的异常包装为新的异常类,并在新的异常类中封装了原始异常类,这样做的目的在于找到异常的根本原因。
这篇文章很好:http://my.oschina.net/yanquan345/blog/204498
在我查过的资料中,以《Effective Java》书中对异常处理设计的研究得最系统,本文很多思想来自于它,下面我把其中的几条原则翻译(非直译)并贴上:
第57条:只对异常情况使用异常。(说明:即不要用异常处理控制正常程序流)。
第58条:对可恢复异常使用编译时异常,对编程错误使用运行时异常。
第59条:应避免不必要的编译时异常:如果调用者即使合理的使用API也不能避免异常的发生,并且调用者可以对捕获的异常做出有意义的处理,才使用编译时异常。
第60条:应偏好使用自带异常
第61条:抛出的异常应适合本层抽象(就是上面说的转译)
第62条:把方法可能抛的所有异常写入文档,包括运行时异常
第63条:用异常类记录的信息要包含失败时的数据
第64条:力求失败是原子化的(解释:就是如果调用一个方法发生了异常,就应该使对象返回调用前的状态)
第65条:不要忽略异常