That's the way finally works. The snippet
try {
    throw new Exception();
} catch(Exception e) {
    throw new Exception();
}
will complete abruptly, but the finally clause will kick in and when it returns it discards the original reason for completing the statement.
This is explained in section Blocks and Statements in the Java Language Specification. I've highlighted the relevant path in your situation:
A try statement with a
  finally block is executed
  by first executing the
  try block. Then there is
  a choice:
 - If
  execution of the tryblock completes normally, then thefinallyblock is
  executed, and then there is a choice:
- If execution
  of the tryblock
  completes abruptly because of athrowof a value
  V, then there is a choice: - If
  the run-time type of V is
  assignable to the parameter of any
  catchclause of thetrystatement, then the
  first (leftmost) suchcatchclause is selected.
  The value V is assigned to the
  parameter of the selectedcatchclause, and the
  Block of thatcatchclause is executed.
  Then there is a choice: - If the
  catchblock completes
  normally, then thefinallyblock is
  executed. Then there is a choice:
- If the
  catchblock completes
  abruptly for reason R, then thefinallyblock is
  executed. Then there is a choice: - If the
  finallyblock completes
  normally, then thetrystatement completes abruptly for
  reason R.
- If the finallyblock completes abruptly for reason
  S, then thetrystatement completes abruptly for
  reason S (and reason R
  is discarded).
 
 
- If the run-time type of V
  is not assignable to the parameter of
  any catchclause of thetrystatement, then thefinallyblock is
  executed. Then there is a choice:
 
- If execution of the
  tryblock completes
  abruptly for any other reason
  R, then thefinallyblock is
  executed. Then there is a choice: