Why is InputStream.close() declared to throw IOException? - java

The java.io.InputStream.close() method is declared to throw an IOException. Under what circumstances would such an exception actually be thrown?
Edit: Yes I have read the javadoc. Can anybody be more specific than "when an I/O error occurs"? What I/O error can occur while closing an InputStream?

In the case of input stream reading from a file system, an error can be raised while the file system itself updates the last access time metadata, or some other metadata, on a file during closure. Anyway, this happens almost never in practice.
In the case of an input stream reading from a network connection, an error on closure is a bit more conceivable. A normal closure of a network socket actually involves a closure request (TCP/IP FIN packet) being sent over the connection and waiting for the other end to acknowledge this closure request. (In fact, the other end of the connection then in turn sends a closure request, which the closing end acknowledges.) So in the case of a socket input stream, a closure operation actually involves sending traffic over the connection and the closure can thus fail with an error.
Note that in many implementations, close() generally doesn't throw an IOException if the stream is already closed; it simply fails silently to close the stream again.

I'm looking through the Java source code, and have found something interesting which is indicative of the IOException reason. InputStream is an abstract class. We therefore can't predict the kind of input which will be closed, so it's good to keep information flowing.
Whatever code uses that input stream needs to be able to throw an IOException, because there is a chance that closing the input stream may fail. If it fails, whatever's using the implementation needs to know about it, because there's a good chance it needs to be handled.
It's important to understand the layout of the Exception structure in Java. Every exception, of course, extends Exception. However, there are also broader categories of exceptions: java.lang.IOException is one of these, and covers all possible input/output exceptions. When we say there has been an I/O error, we're referencing anything which falls under IOException. As a result, many exceptions extends this one, e.g. FileNotFoundException, EOFException, etc. as it's important to have a broad, overarching exception to manage these.
As a result, any IO class will need to be able to throw any of the various IOExceptions on close. close() therefore must throw IOException - this gives its implementation the ability to throw any of the extensions of IOException as well. This is why close() throws IOException - exceptions are inherited, and you need to be able to any of the IOExceptions when closing a stream.
Here are a couple scenarios worth noting:
You can't close an IOStream twice, though this generally doesn't throw an exception if you do
The content becomes inaccessible (e.g. a disk was unmounted) (The close() is actually critical for the operating system, as it needs to have an indicator of when the file is no longer busy)
The generic source has closed
Any generic failure not covered by all other subclasses of IOException (e.g. FileNotFoundException)
You can check what caused an IOException by running Exception.getMessage().

The underlying close system call will have to be made eventually, e.g. on linux http://linux.die.net/man/2/close. That call is documented to fail with EIO: "An I/O error occurred." So the reason is, that the underlying file system close call can fail.

I have wondered about this myself and have done a little research on this topic few years ago. This is what I know....
If you look at the javadoc in the link you provided, it clearly states that "The close method of InputStream does nothing", so there is no way it would throw an exception, correct? But then looking at all of the subclasses of IOException you will see that there are many situations where subclasses of inputstream may not be able to close the stream. So my best guess is that this exception is designed for subclasses to make use of it.
http://docs.oracle.com/javase/6/docs/api/java/io/IOException.html
In some cases, it is nothing more than a nuisance, and in others it clearly indicates that something went wrong. It all depends on what type of inputstream implementation you are making use of.

Related

In Java, can a process pipe stream reader encountering an IOException recover?

I have some Java code, which starts other processes and reads their output using a BufferedReader, by calling java.io.BufferedReader#readLine() in a loop. Sometimes I see that java.io.BufferedReader#readLine() throws IOException, e.g. when the process quits unexpectedly (such things can happen in my case) etc.
The question is: what is the appropriate handling of an BufferedReader#readLine() throwing IOException: is there any case, when reading from the stream again could continue consuming the process output (assuming it was some kind of transient error), or does IOException mean the stream is in failure and should be abandoned and closed?
I guess the whole issue boils down to one thing, if a a pipe stream encountering an I/O error can later recover from it and continue reading or not. My gut instinct tells me, it depends on the underlying operating system / JVM implementation, but I would love to hear inputs from people better versed in this topic than myself.

Java NIO Selector.open() IOException

Whilst using the java.nio.channels.Selector object I can't help but notice that the factory creation method Selector.open() throws an IOException.
Aside from being a pain to handle yet another IOException, I don't get how opening the selector can possibly be an I/O operation not to mention somehow fail at it and throw an IOException.
The code inside the Selector class to open is as follows:
public static Selector open() throws IOException {
return SelectorProvider.provider().openSelector();
}
noting that it defers to the SelectorProvider object I went to look at the code for openSelector(). As follows:
public abstract AbstractSelector openSelector()
throws IOException;
Looks like the class is being loaded dynamically at runtime which puts even more mystery to how these Selectors are being constructed.
The class responsible for creating the Selector if "dynamic loading" fails is sun.nio.ch.DefaultSelectorProvider which I don't have the source code for, so thats as far I can I go in terms of tracing the source of the IOException.
Java's javadoc on Selectors do not help at all they merely state:
Throws: IOException - If an I/O error occurs
If anyone has any insight regarding this bazaar IOException created by Selector.open() please let me know. Additionally answer a more practical question, should the IOException be "properly" handled (e.g. messagebox, flashing lights, toolkit beep sounds, etc) or just tucked away in a log/empty catch block.
The short answer is that it's platform and implementation specific, so you pretty much have no choice; you should catch it and deal with it. And since it's going to be a really rare event (after which you won't have a Selector), it's probably a bells-and-whistles thing. Option B is ignore it and let it hit the top of the stack and halt things.
The long answer is that on Linux, with the current default implementation, it's not going to throw. If it's >= 2.6 kernel, openSelector() is going to instantiate and return a EPollSelectorImpl. If it's < 2.6 you get a PollSelectorImpl. Neither of those class's constructors throws an IOException.
On Windows, however, you get a WindowsSelectorImpl whose constructor does throw IOException. I'd have to dig deeper to find out what would cause it but obviously something can.
Again though, it's an implementation detail, so it could always change in the future.
You can pull the complete source for the openjdk to look at the source for those classes.
It allows the implementation to throw IOExceptions for reasons which naturally aren't specified at the API level. For example, the Windows implementation of Selector uses a selection tree whose internal nodes are pipes to handle cases where the number of selectable channels exceeds the Windows maximum. So the Selector has to be able to open a pipe, and this can fail.

How do you know all the exceptions a method can throw

Is there a way to get some details regarding exception safety aspects of Java's standard classes? Mainly working with C++ and C#, I'm confused with Java exception specifications, so I need to understand the proper way of working with exceptions.
To be more specific, let's consider ServerSocket. It starts listening for incoming connections as soon as its object is constructed. Then, you should use accept() to accept the connection (if someone tries to connect).
In case you've previously configured your server socket with setSoTimeout(), there's a change that accept() will throw SocketTimeoutException because nobody tried to connect in a specified period of time. That's fine, server socket is still usable, so you just call accept() once again.
But SocketTimeoutException is not the only thing that accept() may throw. What does all the other exceptions mean? If I wrap call to accept() with 2 catch clauses: for SocketTimeoutException and IOException, can I still safely use the related ServerSocket instance after I got into IOException clause?
I'd really appreciate both Java-wide and ServerSocket-specific answers.
It is not safe to reuse the object. For such a question I would always look into a source, that is the reason it is open.
So if you look into that one: http://kickjava.com/src/java/net/ServerSocket.java.htm you notice that in accept() a SocketException (inherits from IOException) is thrown if the socket is closed or not bound anymore. Both states indicate that the ServerSocket is not valid anymore.
So for this class, generally, if you fail with an exception, always try to gracefully close the ServerSocket in a finally block and then recreate it.
Additionally on your Java-wide question scope: Always look into the source and understand what the interface is doing. If it is mission-critical write tests that reproduce the behaviour (should not be easy at all with such a low-level api).
Finally - is Java consistently doing such things that way? No. Some classes are stateless, others are not (like ServerSocket), some are thread-safe, others not. And you need to understand - either from the documentation or (mostly) from the code - what state they build in order to understand what to do when an Exception knocks you off from the main path.
Most people curse those checked Java exceptions, because most of them (as with most of the IOExceptions) are not really recoverable in a meaningful way. Most of the time, they argue, you cannot understand each and every fine corner case. Which is the reason why many complex frameworks may retry twice or thrice if they think in this case they might, but finally throw a RuntimeException to a top framework layer. There they make something useful out of it (a meaningful error providing context) and log all the details they have, which is a huge stack trace most of the time. A great resource of knowledge, feared by many developers.
So what can you do if you could not recover from an untested corner-case problem? Throw up (probably with a some subclass of RuntimeException) the most meaningful stacktrace annotated with all the context you have. Setup monitoring. And if you run into a frequent problem, fix it.
Yes. The object still exists - May be in an error state in which case it will throw other exceptions until that is rectified.
If you read the specification for ServerSocket, you will see that it throws an IOException "if an I/O error occurs when waiting for a connection." Is it safe to accept() on the socket again? Yes. Are you going to get the same Exception thrown again? Likely so.
I have not yet found an easy way to see if an object is still in a usable state. Each object makes its own rules.
In your specific case with ServerSocket I would try one of two different things:
Run netstat or some other utility to see what the OS thinks that the socket is doing. If the OS doesn't think it is listening, then something happened.
or
Write a test program that will throw the exception and see what it does. I do this all the time (especially with proprietary software). It would be harder in the ServerSocket case you picked, since all of the scenarios I can think of (e.g. address in use, insufficient privileges, etc.) would never result in an object being still valid.
But SocketTimeoutException is not the only thing that accept() may throw. What does all the other exceptions mean?
According to the javadoc, the declared exceptions are IOException, SecurityException, SocketTimeoutException and IllegalBlockingModeException. The SecurityException and IllegalBlockingModeException only occur in specific contexts and you should not attempt to catch and handle them. (They are not problems you want to try to recover from!) The IOException case occurs when "some other I/O error" occurs. The javadoc does not specify what those I/O errors might be, but possibilities might include such things as:
the address to which you have bound is no longer valid
a transport protocol error has occurred
some error (resource issue, bug ...) occurred in the OS protocol stack
(The fact that the javadoc doesn't say which IOException subclasses might be thrown is a hint that you shouldn't try to do clever things to try to recover. If you do, your code is likely to be platform dependent.)
If I wrap call to accept() with 2 catch clauses: for SocketTimeoutException and IOException, can I still safely use the related ServerSocket instance after I got into IOException clause?
Yes and no. It is safe in the sense that you won't put your application into a worse state than it is already in. On the other hand, there is no guarantee that the next accept call won't fail with the same problem.
If your application is intended to run as an unattended server, I don't think you have much choice but to log the IOException and try again ... hoping that the problem is transient.
You can find your answer to the javadoc of setsoTimeout, it says :
Enable/disable SO_TIMEOUT with the specified timeout, in milliseconds. With this option set to a non-zero timeout, a call to accept() for this ServerSocket will block for only this amount of time. If the timeout expires, a java.net.SocketTimeoutException is raised, though the ServerSocket is still valid. The option must be enabled prior to entering the blocking operation to have effect. The timeout must be > 0. A timeout of zero is interpreted as an infinite timeout.

when does java.util.zip.ZipFile.close() throw IOException?

Under what circumstances would java.util.zip.ZipFile.close() throw an IOException? Its method signature indicates that it can be thrown, but from the source code there doesn't seem to be any place where this could happen, unless it's in native code. What corrective action, if any, could be taken at the point where that exception is caught?
From the API docs on ZipFile.close():
Closing this ZIP file will close all of the input streams previously returned by invocations of the getInputStream method.
And InputStream.close() throws an IOException, so ZipFile.close() has to throw it too. According to the API docs for InputStream.close(), it throws an IOException "if an I/O error occurs". That's not very descriptive but it's casting a wide net. InputStreams can represent streams coming from the filesystem, network, memory, etc. InputStreams can involve buffers that need to be flushed, sockets that need to be closed, resources that need to be freed, locks that need to be freed, etc. IOExceptions can happen for a variety of reasons.
From man close(2):
Not checking the return value of close() is a common but nevertheless serious programming error. It is quite possible that errors on a previous write(2) operation are first reported at the final close(). Not checking the return value when closing the file may lead to silent loss of data. This can especially be observed with NFS and with disk quota.
I'm not sure but I think IOException is thrown when one of the following events happen:
The zip file was deleted by something/someone outside of the application.
When the drive that contains the zip file is unmounted/disconnected
A lot more events might be the reason but those are the only two I could think of right now.
The documentation for ZipFile.close() says:
Closing this ZIP file will close all of the input streams previously returned by invocations of the getInputStream method.
Presumably the native close method is performing the close the InputStreams.
The close method of InputStream has IOException as a checked exception.
The most likely cause is an out of space condition on the filesystem where the zip file is being written error in the underlying filesystem. Unless you can identify the cause and work around it on the fly, all you can do is report the condition to the user.

Why do IOExceptions occur in ReadableByteChannel.read()

The specification of ReadableByteChannel.read() shows -1 as result value for end-of-stream. Moreover it specifies ClosedByInterruptExceptionas possible result if the thread is interrupted.
Now I thought that would be all - and it is most of the time. However, now and then I get the following:
java.io.IOException: Eine vorhandene Verbindung wurde vom Remotehost geschlossen
at sun.nio.ch.SocketDispatcher.read0(Native Method)
at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:25)
at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:233)
at sun.nio.ch.IOUtil.read(IOUtil.java:206)
at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:236)
at ...
I do not unterstand why I don't get -1 in this case. Also this is not a clean exception, as I cannot catch it without catching any possible IOException.
So here are my questions:
Why is this exception thrown in the first place?
Is it safe to assume that ANY exception thrown by read are about the socket being closed?
Is all this the same for write()?
And by the way: If I call SocketChannel.close() do I have to call SocketChannel.socket().close() as well or is this implied by the earlier?
Thanks, Steffen
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.
Per the documentation here:
Checked exception received by a thread
when another thread interrupts it
while it is blocked in an I/O
operation upon a channel. Before this
exception is thrown the channel will
have been closed and the interrupt
status of the previously-blocked
thread will have been set.
This suggests that the thread that owns the ReadableByteChannel is being interrupted by another thread in your application... is this the case?
If another thread was closing the channel, I would expect you would see a AsynchronousCloseException.
I don't see a reason why you couldn't catch the ClosedByInterruptException explicitly and allow any other exceptions to be handled higher up the stack:
try
{
rbc.read(dst);
}
catch ( ClosedByInterruptException cbie)
{
/* handler */
}
As for write(), there is no write() method for ReadableByteChannel, however, the WritableByteChannel, does have a write() method and it can throw the same exceptions.

Categories