Exception handling code must guarantee its fail-safe mechanism, and one of the important rules is as follows:
The try-catch-finally last exception that is thrown in the block is passed in the call stack.
All early exceptions will disappear.
If catch finally an exception is thrown from one or block, then this exception may cause the exception that is try caught in the block to be hidden. This can be misleading when you are trying to determine the cause of the exception.
The following is a non-fail-safe classic example of exception handling:
null;try { new"myFile.txt" ); /* do something with the stream */}catch ( IOException e ) { thrownewWrapperException( e );}finally { try { input.close(); } catch ( IOException e ) { thrownewWrapperException( e ); }}
If FileInputStream the constructor throws an FileNotFoundException exception, what do you think will happen?
The block is executed first catch , and the block will only re-throw the exception that is wrapped in WrapperException .
Next, the finally block is executed to close the input stream. However, because the FileInputStream constructor throws an FileNotFoundException exception, the reference variable "input" will be the null . The result will be an finally exception thrown from the block NullPointerException . NullPointerExceptionis not catch ( IOException e ) caught by the clause, so it will be passed in the call stack. And the first catch block is thrown WrapperException away.
The correct way to handle this situation is to check whether the reference allocated in the block is the first before calling any methods try null . For example, like this:
inputstream input = null ; try {input = new fileinputstream ( "myFile.txt" ); //do something with the stream } catch (IOException e) {//first catch block throw new wrapperexception (e);} finally {try {if (input! = null ) Input.close (); } catch (IOException e) {//second catch block throw new wrapperexception (e); }}
But even if this is still a problem, let's assume that the "myFile.txt" file exists, so the "input" reference now points to a valid one FileInputStream . We also assume that an exception is thrown when the input stream is processed, when the first catch clause is caught and thrown, and the WrapperException WrapperException clause is executed before it is passed to the call stack finally . If the input.close() call fails, it is thrown and IOException caught and thrown by the second catch clause WrapperException , which disappears again from the first catch clause WrapperException , and only the second catch is WrapperException passed to the call stack.
As you can see, failsafe (fail safe) exception handling is not always worthless. The InputStream processing examples are not even the most complex examples you can encounter. There is more likelihood of errors in the transactions in JDBC. An exception may occur when you try to commit, then roll back, and finally try to close the connection. All of these possible exceptions should be handled by exception handling code, so none of them will cause the first thrown exception to disappear. One way to do this is to make sure that the last exception that is thrown contains all the exceptions that were previously thrown, so that the developer can understand the cause of the error.
The features in Btw,java 7 try-with-resources make it easier to implement fail-safe exception handling.
Original link: http://tutorials.jenkov.com/java-exception-handling/fail-safe-exception-handling.html
Java fail-safe exception handling