About a year ago I patched my own log4j to fix the fact that it can swallow
InterruptedException
via InterruptedIOException
. Then I filed a bug against log4j, and got into an email conversation with Curt Arnold, who rightly pointed out that there were other scenarios where InterruptedException
could be easily ignored. Anything that wraps an InterruptedException
or InterruptedIOException
and rethrows something that doesn’t derive from them is effectively ignoring the intended effect of a thread interrupt. The most common examples of this arejava.lang.reflect.Method.invoke
andjava.lang.reflect.Constructor.newInstance
which both throw java.lang.reflect.InvocationTargetException
, which can have this problem.
The title of this post may be a bit misleading;
java.io.InterruptedIOException
doesn’t cause this problem, it just makes it at least twice as difficult, because you must always check for both InterruptedException
and InterruptedIOException
in wrapped exceptions. But it also means that any method that throwsjava.io.IOException
must have special handlers for an interrupted thread.
I tried to find a bug in Sun’s database that warns about
InterruptedIOException
and these cases, but the closest I could find was Sun bug 4385444. That doesn’t really have anything to do with it.
When I first saw the changes made for
java.nio
for interruptible IO, I thought the use of InterruptedIOException
was clever and elegant. But because of the very special nature of InterruptedException
, I changed my mind—of course, there wasn’t much option, because java.nio
integrates with existing java.io
interfaces and methods which already do not throw InterruptedException
, therefore they had to follow that path. It’s really a difficult situation; it isn’t the first case in Java of a hidden or wrapped InterruptedException
, it just makes it more widespread. Now you have to handle an interrupted thread anywhere java.io.IOException
is thrown.
Note that on Solaris (x86 and Sparc)
java.io
methods can also throwInterruptedIOException
. You don’t need to use java.nio
to see this effect. On other platforms you only have to worry about this if you (or things you call) usejava.nio
.
I’ve come to the conclusion that thread interrupts are so special, and currently so difficult to deal with, that Java should treat
InterruptedException
as a third type of exception: one that is implicitly thrown from every method. Of course this opens up its own can of worms, not to mention that it’s about 15 years too late to make such a change.
This also speaks to the fact that you should be following a pattern where it’s rare that you catch exceptions that you don’t understand, and should be catching them as far up as possible, where you can centralize your exception handling. I think this is also a good case for frameworks like Spring and Seam which use AoP; each method invocation can have a carefully thought out exception handler, either via your own AoP, or directly handled in the framework.
Update I’ve found bug 4176863 which is related to this issue, but more importantly, the paper Java Thread Primitive Deprecation. I had read this long, long ago, and thought it important to link here.
No comments:
Post a Comment