Terminating a finally block abruptly preempts the outcome of the try and catch
blocks, and will cause the result of any previously executed return or throw
statements to be ignored. Finally blocks should be written so they always
complete normally.

Consider the following code. In the case where `doWork` throws `SomeException`,
the finally block will still be executed. If closing the input stream *also*
fails, then the exception that was thrown in the catch block will be preempted
by the exception thrown by `close()`, and the first exception will be lost.

```java
InputStream in = openInputStream();
try {
  doWork(in);
} catch (SomeException e) {
  throw new SomeError(e);
} finally {
  in.close(); // exception could be thrown here
}
```

This code is easily fixed using try-with-resources. Below, the input stream will
always be closed, and if `doWork` fails and an `IOException` is thrown, then the
try-with-resources uses the `Throwable.addSuppressed()` method added in Java 7
to propagate both exceptions back to the caller.

```java
try (InputStream in = openInputStream()) {
  doWork(in);
} catch (SomeException e) {
  throw new SomeError(e);
}
```

If Java 7 is not available, we recommend Guava's
[Closer API](https://guava.dev/releases/snapshot/api/docs/com/google/common/io/Closer.html).

```java
Closer closer = Closer.create();
try {
  InputStream in = closer.register(openInputStream());
  doWork(in);
} catch (Throwable e) {
  throw closer.rethrow(e);
} finally {
  closer.close();
}
```
