Hi all I understand that if we read bytes from an InputStream and we have finished reading all the bytes (or we do not intend to read to the end of stream), we must call close() to release system resources associated with the stream.
Now I was wondering if I read bytes and it throws a java.io.IOException, am I still required to call close() to release system resources associated with the stream?
Or is it true that on errors, streams are closed automatically so we do not have to call close() ?
The OS itself might close the streams and deallocate resources because the process (namely, the JVM) terminates, but it is not mandated to do so.
You should always implement a finally block where you close it in cases like these, e.g. like this:
InputStream is = null;
try {
is = new FileInputStream(new File("lolwtf"));
//read stuff here
} catch (IOException e) {
System.out.println("omfg, it didn't work");
} finally {
is.close();
}
This isn't really guaranteed to work if it threw in the first place, but you'll probably wanna terminate at that point anyway since your data source is probably messed up in some way. You can find out more info about it if you keep the InputStream's provider around, like, if I kept a ref to the File object around in my example, I could check whether it exists etc via File's interface, but that's specific to your particular data provider.
This tactic gets more useful with network sessions that throw, e.g., with Hibernate...
Related
I want to fetch an HTML page and read in with BufferedReader. So I use try-with-resources to open it handles IOException this way:
try(BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()))) {
} catch(IOException e) {
throw e;
}
Is this a good pattern to catch and instantly throw? And what if I omit try at all and state that function throws IOException? If then any potentional memory leak?
Much appreciate any advice!
A catch block is not required in a try-with-resources statement. You could write the following, which would mean exactly the same as your original code:
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(url.openStream()))) {
// do something
}
So, you can leave out the catch block, if all you ever do there is immediately throw the same exception again.
You do want the try block however, so that the BufferedReader and underlying stream(s) are automatically closed at the end of the block.
Is this a good pattern to catch and instantly throw?
No, catching and immediately re-throwing the same exception does not add anything useful.
To add to #Jesper's excellent answer, you do want to include the try block so that the BufferedReader will be closed right away. If you don't do this, it'll eventually be closed when the object is garbage collected, so it isn't technically a resource leak in the sense that the resources would eventually be reclaimed; however, the "eventually" part is potentially problematic because there are no guarantees as to exactly when that'll happen. Thus, a bigger issue is whether this would create race conditions if it's using a resource that needs to be reused eventually.
I'm not very familiar with the implementation details of that exact class, so this is somewhat speculative, but one example of an issue you can run into with some classes that perform network calls if you fail to return resources to the operating system promptly is port exhaustion.
By way of another example, if you are modifying a file, the file could remain locked until the GC happens to release the file lock by cleaning up the relevant object.
If I have stream (InputStream or OutputStream) which I did not create but was rather passed to my method as a parameter, should I be closing that stream? Here's an example:
void method(InputStream in) {
try {
//Do something
}
finally {
if(in != null) {
in.close(); //Is this needed and correct?
}
}
Really, "it depends".
As a general rule, you should not close a stream that you didn't have responsibility for opening, but to give a correct answer we would have to understand the context.
It's very possible that the delegation of responsibility requires your method to consume from and close the stream - if this is the case then it should be explicit in the code.
If your method is named readFromStreamAndClose(InputStream in) then the fact that your method closes the stream is very obvious.
In the case that you open the stream yourself, you can always use a try-with-resources block which will close the stream for you - at the same level of abstraction as it was created. In this case - your method (which is called at a lower level than when the stream was opened) should not close the stream.
Generally it is not recommended to close the stream which is not associated to that class.
Following are the reasons,
Streams passed to that method may be used in some other place.
Reusable streams are available in java. If the stream is closed it
cannot be reopened and reused.
In case of Exception when closing the stream you don't know how to
handle that. Because you are dealing with general inputstream and it
may come from any place like File, Network etc.
The class opens the stream is responsible for closing it.
I don't think that the JVM spec makes any guarantee about that. You really are supposed to finally close these resources.
When the process ends, the operating system will release all resources associated to it (including memory, file handles, and network sockets).
There are OS facilities to check about open files and streams
No you don't have to do it because it may be used somewhere further in the code.
You do document the method with: "Closes the stream" and change the name method to like readAndClose.
Or create a parameter boolean closeStream and close if true.
Also if the stream doesnt support mark/seek/reset there's no reason to keep it open.
I am using Java 1.6.
I am facing some memory heap issues and in the heap dump I can see that ObjectOutputStream objects are consuming more memory.
In my application at some places, I have used ObjectOutputStream but missed to close the stream in some of the methods.
So will this impact the performance ??
Will the stream remain open and will it consume Heap Memory ??
Will Java close the stream when the method is finished where ObjectOutputStream is used but stream is not closed ??
No, java will not close the stream all by itself.
How badly leaving it open will affect your performance depends on the rest of the code. If the method is often, it will be a serious problem. Regardless of that, it's just way better practice to close your streams.
It's a great reason to upgrade to java 7, where you can write
try (ObjectOutputStream stream = ...) {
...
}
Here java will close the stream for you when you're done with it, no matter how that happens.
Off course you can achieve the same behaviour in java 6 but it's more work.
In Java 1.6, looking at the docs :
close
public void close()
throws IOException Closes the stream. This method must be called to release any resources associated with the stream.
must is pretty strong, so I would say that yes, you must call it.
We can have a look at the source :
public void close() throws IOException {
flush();
clear();
bout.close();
}
It does clean a few things. It also implements the interface AutoCloseable, which :
public interface AutoCloseable
A resource that must be closed when it is no longer needed.
So, call the close() method.
Note : Even if close() did nothing I would still call it to give a clear indication in the code that this is not to be used anymore, but that's probably a personal preference.
Adding some comments to Stef's great answer:
From another point of view, you may ask yourself: what is the reason for leaving the ObjectOutputStream open in some cases? If you don't use it anymore, then you should definitely close it as soon as possible. It is a good idea to follow this convention.
The close method makes sure that there are no references to the stream so the resources can be garbage collected; using it is definitely something you want to do in order to have a healthy memory space.
What I am usually doing is having a try {} finally {} without a catch {}:
public static void closeStream(OutputStream out)
{
if (out != null) out.close();
}
...
ObjectOutputStream out = null;
try
{
//do something
}
finally
{
closeStream(out);
}
You can of course use a catch block if you need to, or add throws to your method. Either way, this way you can be sure that stream resources are released.
In the following code, where should the close locate? Should it be in the try clause or in finally? If it is finally, should it be enclosed with another try-catch? Thanks.
PrintWriter out = null;
try {
out = new PrintWriter(
new BufferedWriter(
new FileWriter("out.txt", true)));
out.println("the text");
} catch (IOException e) {
System.err.println(e);
} finally {
if (out != null) {
out.close();
}
}
See the documentation for try-with-resources. If you're using at least Java 7, there's a nice syntax for this. Otherwise, the finally block is appropriate, since it should be closed in both the normal and exceptional cases.
Put it in the finally block.
Because you should close the Writer in either case (exception or no exception).
To handle close properly, one should ensure that it gets called whether or not an exception occurs in the main-line code, but one should also ensure that if close gets called following an exception in the main-line and then throws an exception itself, it won't cause the main-line exception to be discarded; depending upon various factors including whether the object was open for reading or writing, it may be desirable to either let the main-line exception percolate up (perhaps encapsulating information about the close failure), log or encapsulate the main-line exception but have the close failure percolate up, or throw a "double fault" exception which encapsulates both of the others.
The try-with-resources feature of Java 7 provides pretty good behavior for many scenarios: if an exception occurs in try and another in close, the latter exceptions get added to a list of suppressed exceptions (which exception-handling code should look for). If a method is supposed to grab data from a wireless sensor and write it to a file, and if the caller will expect that in the event of sensor trouble the file will hold as much information as was read successfully, then a failure to close the file may be more important than a sensor failure [if the sensor e.g. only includes "return oldest item" and "delete oldest item" commands, then if the file closed properly an exception during sensor communication would mean that any data which was no longer in the sensor would be in the file. If the file didn't close properly, that would imply that there might have been permanent data loss, and someone should be told about it.
Code to handle the "sensor capture" scenario would end up being a bit icky: the sensor read logic would be placed within a try block whose finally would capture any exception to a variable. The finally block would then have to use its own try block for the close; if an exception occurs there, throw a custom writeFileCloseFailure exception which encapsulates both the exception (if any) from the try block and the exception from the close; otherwise, rethrow the exception (if any) from the try block. Note that since ioException could represent either a failure to get data from the sensor (somewhat expected and tolerable) or a failure to write the file (very bad), wrapping in another exception type would allow the caller to distinguish those conditions.
I have some questions regarding java finalization.
For example I have one class FileHelper and this class is associated with reading file,writing file,etc.
Now my question is, I have one method writeFile() in FileHelper class.Now If I want to close that file
should I override the finalize() method and close the file or can I close the file inside the writeFile() method itself? Which is the right way to do? I have declared my File variable as a member variable. If overriding is a bad idea, then why do we want to override finalize() method? which scenario? I have read many articles,where they are saying to close system resources such as file,font etc..
The best practice is to close the file as soon as possible. If you have static method in FileHelper (assuming that your Helper is a bunch of static "helper" methods) I would close the file inside
static void writeFile(String fileName, String text) { // Exception
// Open file here
// write text
// close it
}
The purpose of overriding finalize is release the unmanaged resources e.g. files in case someone forget to do it. If someone use your helper this way
FileHelper fileHelper = new FileHelper(file);
fileHelper.writeFile(text);
// forgot to fileHelper.close();
and you have overridden the finalize and call close() inside when GC runs the file will be closed. The problems:
As I mention earlier file should be closed as soon as possible (but not sooner ;) )
It's indeterministic (No body knows when GC will start)
This should be used only to prevent the case when the caller forgets to close the file
The finalize() method would only get invoked when the Java Garbage Collector is about to reclaim the object. It is a bad practice to release file handle in the finalize method.
It may result in java.io.IOException: Too many open files as you cannot guarantee when the garbage collector would run.
A better option would be to close the file reader/writer object in the finally block. As it is guaranteed to run.
finally {
// Always close input and output streams. Doing this closes
// the channels associated with them as well.
try {
if (fin != null)
fin.close();
if (fout != null)
fout.close();
} catch (IOException e) {
}}
fin and fout are FileInputStream and FileOutputStream objects.
Using finalizers is a bad idea, in nearly all circumstances. The Java specs state that there is no guarantee that finalizers will ever be run. And even if they do, you have no control over when this may happen.
Using finalizers as the primary mechanism to close files is always a bad idea. Why? Because if the GC doesn't run for a long time, your application is liable to run out of file descriptors, and file open attempts will start failing.
The best way to deal with opened streams is to keep them in local variables and parameters, and use try { ...} finally to make sure that they are always closed when you have finished with them. Or in Java 7, use the new "try with resource" syntax.
If you need to put the stream in a member variable, you probably should make the parent class implement a close() method that closes the streams, and use try { ...} finally to make sure that the instances of the parent class get closed.
It should also be noted that there is little point using a finalizer to close "lost" streams. The stream classes that use external resources that need to be closed already have finalizers to do this.
Overriding finalize() is not a good practice. I would have done it in the code.