Funny, but somebody today already posted a link to Fallacies of Distributed Computing.
In your case, as a fine German to English translator tells me An existing connection was forcibly closed by remote host
.
When you deal with I/O, and specifically Socket I/O, you have to be prepared that any IOException would be thrown at you.
Some of them, like ClosedByInterruptException
you may handle intelligently. Others, you may
- Add
throws
declarations to you method and let callers deal with IOExceptions
- Wrap IOExceptions into checked exception specific to your subsystem
- Wrap IOExceptions into RuntimeException specific or not to your subsystem
- Log IOException and continue.
In any case, once you get IOException, you probably cannot do much to communicate with that channel. So you may just close your connection and retry later.
BTW, read
will only return -1 to you if you SUCCESSFULLY reached end-of-stream. In your case, I am sure, the connection is closed midstream.
EDIT in reply to OP comments
Can I prevent a channel to be
interruptible?
No, this is a property of specific channel that you are using. If it implements InterruptibleChannel
, then it IS interruptible, and will be closed upon receipt of thread interrupt. java.nio.channels.SocketChannel
is interruptible
The docs for
ClosedByInterruptException state:
"Checked exception received by a
thread when another thread interrupts
it while it is blocked in an I/O
operation upon a channel." Still how
can it be blocking, if it is
NON-blocking IO?
If you look at specification of ReadableByteChannel.read
you will see that the method is declared to only throw IOException
. Then in JavaDoc it hints what kind of specific IOExceptions and undre what conditions may be thrown by a standard java.nio implementation of this interface. This is one of the example of cooperative programming. The declarer of the interface tells the implementer how they should implement the method and what exceptions should they throw under what conditions.
For example, if I implement the read method in my exotic channel I may choose to totally ignore the specification and not throw any of exception in the declaration. The user of my class though will probably pay a heavy price when encountering unexpected behavior and will probably dump my implementation in favor of more robust one.
In any case, I think you are confused with how you should react to different exceptions declared in read method.
First of all, not every exception in read method specification may be thrown. Case in point ClodesByInterruptException
most likely will NOT get thrown in case you are using a NON-blocking I/O. On the other hand some implementers may choose to close the channel upon receipt of the interrupt and throw this exception when you attempt to read even if you are in NON-blocking I/O. But you really should not get concerned with that decision, because:
- You probably control whether current
thread is interrupted or not
- This is just the other kind of
IOException, and by default should
be treated as fatal
And yes, the example IOEception is
fatal, but my question is: Are they
ALL?
Remember, that your framework should function normally, or shutdown gracefully when any kind of exception is thrown. For example your code, or library code at any point can throw unchecked ( Runtime ) exception. Only testing and more intimate knowledge of your environment can tell you which exceptions are truly fatal and which can be handled safely.
Because frameworks are written by people they also have bugs, deficiencies, etc. So there may be a case when IOException is thrown, but the underlying channel is still OK. Unfortunately these conditions can only be found with blood and guts in real production environment. Here is one of the example where IOException thrown by a socket can be totally ignored: http://bugs.sun.com/view_bug.do?bug_id=4516760.
So, start by writing generic handler for all IOExceptions and treat them all as fatal, relax it for specific conditions that you find out in production.