New error handling inspection request: finally clause masks uncaught except

Dave / Jetbrainers / et.all

Lemme know if this already exists and I'm just not seeing it, but a 'bug' I've been hit with twice now in the past month strikes me as a great idea for an inspection (one of my co-workers happily pointed out that Eclipse has this one already).

The problem is with the finally clause masking any thrown exception silently.

Take for example:

try {
// Do something which throws an IOException
} catch (IOException e) {
// handle it
} finally {
// do your clean up and move on...
}

Now, if I change this to:

try {
// Do something which throws an IOException
// Do something which also throws a FooBarWhimperException
} catch (IOException e) {
// handle it
} finally {
// do your clean up and move on...
}

Idea shows no bugs, no problems, javac happily compiles it properly, because the finally clause is happily masking the FooBarWhimperException.

My initial thoughts were that javac should complain, but it doesn't (must go read the docs on the finally clause and see if this is documented), so it'd be great to have an intention/inspection that highlights the fact the exception is masked by the finally clause.

Easy? Hard? Already done somewhere?

2 comments
Comment actions Permalink

Mark,

I'm not sure if I really understand your problem: What do you mean with the
finally clause "masks" the exception? The finally clause doesn't have anything
to do with exceptions per se; it's just guaranteed to be executed when its
try-block is left - either normally or abnormally via any exception.

This is an example that can be used to execute code after a return statement
without any exceptions involved:

try { return myObject; } finally { myObject = nextObject(); }

The only weird thing that can happen is if the try-block is left by an exception
and the finally-clause throws an exception as well: The exception from the
frinally block will "win" then.

However, a return statement inside a finally block does mask any exception and
will override any value that is returned from inside the try block. But there's
an inspection for this already: "'return' inside 'finally' block".


Sascha

0
Comment actions Permalink

I think you're misunderstanding the semantics here. In your example, the FooBarWhimperException isn't masked, it is simply never thrown! The IOException is thrown, caught, the catch block executed, the finally block executed, and the example left. The line throwing FooBarWhimperException is never executed.

Java doesn't have any support for resumption semantics for exception. Once an exception is thrown, there is no way to go back to the point of the exception. Other languages have this ("retry" in Eiffel), but not Java. (As a static analyis writer, I'll say that this lack is a Good Thing, as resumable exceptions would make most code analyses much weaker. As a developer, I can't say I've needed resumable exceptions more than once a decade on average.)

Or maybe I'm misunderstanding what you're saying.

The only way an exception can be "thrown away" by a finally-block is if it doesn't return normally. There are already inspections for return/throw/continue/break statements inside finally-blocks. Theoretically, an exception could be masked by a method call in a finally block which throws a (possibly unchecked) exception, but that would probably produce way too many false positives to be useful.

There's also an inspection for thrown exceptions which are caught locally, effectively using a "throw/catch" pair as a downward "goto". That would trigger in this case if the IOException was explicitly thrown, but not if it was thrown from a method call.

Can you give me a link to the semantics of the Eclipse check? Checks in Eclipse that aren't available in IDEA are, of course, an affront to God and Nature, and need to be fixed for the next EAP.

--Dave Griffith

0

Please sign in to leave a comment.