Exclusion from the resource closes, finally hiding the other - who cares?

Firstly, it is a pity that I asked a question about what should be a well-worn topic. I came across a lot of questions with answers suggesting to catch a potential exception (catch and ignore / log) from methods that close resources in finally blocks. This seems to be a common picture. But I have not yet seen anyone explain why. Here is just one example: Try-catch-finally, and then try to catch again .

I understand that any exception thrown from the finally block will β€œmask” any exception thrown in the corresponding try block, but I don’t understand why this is bad. For instance:

Resource r = new Resource(); try { r.use(); other(); } finally { r.close(); } 

My real understanding:

  • If only close throws an exception, we definitely don't want to swallow it.
  • If both use and close throw an exception, this is probably for the same main reason, and it doesn't matter which exception is thrown (will they both contain equally useful information?).
  • If both other and close throw an exception, two unrelated problems arise. It is likely that the one that happened first should spread, but there is no reason to suppose that the first exception caused the second (is it?), So do it.

How am I wrong?

+4
source share
1 answer

If only close throws an exception, we definitely don't want to swallow it.

It is right!

If you use and close the exception, this is probably for the same main reason, and it does not matter which exception is propagated (will they both contain equally useful information?).

Not really. The exception to try could be a NullPointerException , OutOfMemoryError or an actual I / O exception that describes the nature of the problem. Even if this is an I / O exception, the error could leave the thread in an inconsistent state (or even shut down earlier). Calling close() may lead to a completely different error, for example, "stream is already closed", "internal error", or something else.

One mistake in the system tends to cascade dozens of others, sometimes looking very disconnected. Always look for the first exception for the root cause. The rest is just rubbish. A good example is initialization, which failed, and left the object in an inconsistent state. Later, you see a NullPointerException everywhere, but the real problem arose earlier.

If both others and loved ones raise an exception, there are two unrelated problems. [...] there is no reason to suppose that the first exception caused the second (is it?), so it will either.

Actually, both exceptions are imports, but the first is probably more appropriate. Decision? Use AutoCloseable resources in Java 7 and try-with-resources idiom . If an exception occurs during cleaning, it will be tied to the original exception as suppressed:

 class Resource implements AutoCloseable //... 

and then:

 try(Resource r = new Resource()) { r.use(); other(); } 

The exception will look something like this:

 MyException: Exception in use() at Resource.use(Main.java:11) at Main.main(Main.java:16) Suppressed: java.lang.RuntimeException: Exception in close() at Main.close(Main.java:6) at Main.main(Main.java:17) } 
+3
source

Source: https://habr.com/ru/post/1437471/


All Articles