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.
Related
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.
The question says it all.
What are the consequences of not closing the various byte streams?
It is very much emphasized to always do so, but there is no mention of how it causes problems.
Can someone please explain what actually happens?
This is not only byte streams. This concerns anything implementing Closeable.
As the documentation states:
The close method is invoked to release resources that the object is holding (such as open files).
Whether a Closeable holds system resources or not, the rule of thumb is: do not take the chance. .close() it correctly, and you'll be ensured that such system resources (if any) are freed.
Typical idiom (note that InputStream implements Closeable):
final InputStream in = whateverIsNeeded;
try {
workWith(in);
} finally {
in.close();
}
With Java 7 you also have AutoCloseable (which Closeable implements) and the try-with-resources statement, so do:
try (
final InputStream in = whateverIsNeeded;
) {
workWith(in);
}
This will handle closing in for you.
Again: don't take the chance. And if you don't use JDK 7 but can afford Guava, use Closer.
Not closing limited resources such as database connections will dramatically slow down execution, and likely result in errors as those connections run out, with old ones sitting there unused.
Not closing file-streams could result in multiple threads writing to the same file, or files not being terminated properly, or files being locked when another thread attempts to write or read it.
This is a major topic relating to all Closeables, as stated by #fge. There are numerous libraries supplying things such as connection pools and caches for handling problems such as this.
More information:
https://www.google.com/search?q=consequentes+of+not+closing+resources+java
It will hang around util collected by the GC. (thus holding to unmanaged resources (files, sockets etc)
There are several streams including:
ByteArray
File
Filter
Object
Piped
Corba version of the outputStream
Depending on the kind of resource is behind the stream the result could be different. InByteArrayInputStream and ByteArrayOutputStream where the documentation says:
Closing a ByteArrayInputStream has no effect. The methods in this
class can be called after the stream has been closed without
generating an IOException.
But in FileInputStream there is an open file. If you keept it open there is memory reserved and anybody who tries to edit the file will find it locked. In case of doubt always call the close() method.
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.
Assume that I have the following code fragment:
operation1();
bw.close();
operation2();
When I call BufferedReader.close() from my code, I am assuming my JVM makes a system call that ensures that the buffer has been flushed and written to disk. I want to know if close() waits for the system call to complete its operation or does it proceed to operation2() without waiting for close() to finish.
To rephrase my question, when I do operation2(), can I assume that bw.close() has completed successfully?
when I do operation2(), can I assume that bw.close() has completed successfully?
Yes
Close the stream, flushing it first. Once a stream has been closed, further write() or flush() invocations will cause an IOException to be thrown. Closing a previously-closed stream, however, has no effect.
Though the documentation does not say anything specifically, I would assume this call does block until finished. In fact, I'm pretty sure nothing in the java.io package is non-blocking.
The JavaDoc for the java.io.BufferedReader.close() is taken exactly from the contract if fulfills with the java.io.Reader.
The Doc says:
Closes the stream and releases any system resources associated with it. Once the stream has been closed, further read(), ready(), mark(), reset(), or skip() invocations will throw an IOException. Closing a previously closed stream has no effect.
While this makes no explicit claim of blocking until the file system is complete, with this same instance of BufferedReader all other operations will throw an exception if close() returns. Although the JavaDoc could be seen as ambiguous about when the operation completes, if the file system flush and close were not complete when this method returned it would violate the spirit of the contract and be a bug in Java (implementation or documentation).
NO! You cannot be sure for the following reason:
A BufferedWriter is a Wrapper for another Writer. A close() to the BufferedWriter just propagates to the underlying Writer.
IF this underlying Writer is an OutputStreamWriter, and IF the OutputStream is a FileOutputStream, THEN the close will issue a system call to close the file handle.
You are completely free to even have a Writer where close() is a noop, or where the close is implemented non-blocking, but when using only classes from java.io, this is never the case.
A Writer (or BufferedWriter) is a black box that writes a stream of characters somewhere, not necessarily to the disk. A call to close() must (by method contract) flush its buffered content before closing, and should (normally) block before all its "essential" work is done. But this would depend on the implementation and the environment (you cannot know about caches that are below the Java layer, for example). In what respects of the work to be done by the Java writer itself (eg: make the system call to write to disk, in the case of a FileWriter or akin, and close the filehandle) , yes, you can assume that when close() returns it has already done all its work.
In general with any i/o operation you can make no assumptions about what has happened after the write() operation completes, even after you close. The idea of delivery is a subjective concept relative to the medium.
For instance, what if the writer represents a TCP connection, and then the data is lost inbetween client and server? Or what if the kernel writes data to a disk, but the drive physically fails to write it? Or if the writer represents a carrier pigeon that gets shot en route?
Furthermore, imagine the case when the write has no way of confirming that the endpoint has received the data (read: udp/datagrams). What should the blocking policy be in that situation?
The buffer will have been flushed to the operating system and the file handle closed, so the Java operations required will have been completed.
BUT the operating system will have cached or queued the write to the actual disk, pipe, network, whatever - there is no guarantee that the physical write has completed. FileChannel.force() provides a way to do that for files on local disks: see the Javadoc.
Yes, IF you reach operation2();, the stream would've had to have been completely closed. However, close() throws IOException, so you may not even get to operation2();. This may or may not be the behavior that you expect.
I have a question in my mind that, while writing into the file, before closing is done, should we include flush()??. If so what it will do exactly? dont streams auto flush??
EDIT:
So flush what it actually do?
Writers and streams usually buffer some of your output data in memory and try to write it in bigger blocks at a time. flushing will cause an immediate write to disk from the buffer, so if the program crashes that data won't be lost. Of course there's no guarantee, as the disk may not physically write the data immediately, so it could still be lost. But then it wouldn't be the Java program's fault :)
PrintWriters auto-flush (by default) when you write an end-of-line, and of course streams and buffers flush when you close them. Other than that, there's flushing only when the buffer is full.
I would highly recommend to call flush before close. Basically it writes remaining bufferized data into file.
If you call flush explicitly you may be sure that any IOException coming out of close is really catastrophic and related to releasing system resources.
When you flush yourself, you can handle its IOException in the same way as you handle your data write exceptions.
You don't need to do a flush because close() will do it for you.
From the javadoc:
"Close the stream, flushing it first. Once a stream has been closed, further write() or flush() invocations will cause an IOException to be thrown. Closing a previously-closed stream, however, has no effect."
To answer your question as to what flush actually does, it makes sure that anything you have written to the stream - a file in your case - does actually get written to the file there and then.
Java can perform buffering which means that it will hold onto data written in memory until it has a certain amount, and then write it all to the file in one go which is more efficient. The downside of this is that the file is not necessarily up-to-date at any given time. Flush is a way of saying "make the file up-to-date.
Close calls flush first to ensure that after closing the file has what you would expect to see in it, hence as others have pointed out, no need to flush before closing.
Close automatically flushes. You don't need to call it.
There's no point in calling flush() just before a close(), as others have said. The time to use flush() is if you are keeping the file open but want to ensure that previous writes have been fully completed.
As said, you don't usually need to flush.
It only makes sense if, for some reason, you want another process to see the complete contents of a file you're working with, without closing it. For example, it could be used for a file that is concurrently modified by multiple processes, although with a LOT of care :-)
FileWriter is an evil class as it picks up whatever character set happens to be there, rather than taking an explicit charset. Even if you do want the default, be explicit about it.
The usual solution is OutputStreamWriter and FileOutputStream. It is possible for the decorator to throw an exception. Therefore you need to be able to close the stream even if the writer was never constructed. If you are going to do that, you only need to flush the writer (in the happy case) and always close the stream. (Just to be confusing, some decorators, for instance for handling zips, have resources that do require closing.)
Another usecase for flushing in program is writing progress of longrunning job into file (so it can be stopped and restarted later. You want to be sure that data is safe on the drive.
while (true) {
computeStuff();
progresss += 1;
out.write(String.format("%d", progress));
out.flush();
}
out.close();