I was looking at Java Serialization articles and stumbled a number of times across examples where the streams are closed in the try block instead of in a finally block. Can someone explain to me why is that?
Example:
import java.io.*;
public class DeserializeDemo {
public static void main(String [] args) {
Employee e = null;
try {
FileInputStream fileIn = new FileInputStream("/tmp/employee.ser");
ObjectInputStream in = new ObjectInputStream(fileIn);
e = (Employee) in.readObject();
in.close();
fileIn.close();
} catch(IOException i) {
i.printStackTrace();
return;
} catch(ClassNotFoundException c) {
System.out.println("Employee class not found");
c.printStackTrace();
return;
}
System.out.println("Deserialized Employee...");
System.out.println("Name: " + e.name);
System.out.println("Address: " + e.address);
System.out.println("SSN: " + e.SSN);
System.out.println("Number: " + e.number);
}
}
Source: http://www.tutorialspoint.com/java/java_serialization.htm
The try-with-resources Statement
The try-with-resources statement is a try statement that declares one or more resources. A resource is an object that must be closed after the program is finished with it. The try-with-resources statement ensures that each resource is closed at the end of the statement. Any object that implements java.lang.AutoCloseable, which includes all objects which implement java.io.Closeable, can be used as a resource.
The following example reads the first line from a file. It uses an instance of BufferedReader to read data from the file. BufferedReader is a resource that must be closed after the program is finished with it:
static String readFirstLineFromFile(String path) throws IOException {
try (BufferedReader br =
new BufferedReader(new FileReader(path))) {
return br.readLine();
}
}
In this example, the resource declared in the try-with-resources statement is a BufferedReader. The declaration statement appears within parentheses immediately after the try keyword. The class BufferedReader, in Java SE 7 and later, implements the interface java.lang.AutoCloseable. Because the BufferedReader instance is declared in a try-with-resource statement, it will be closed regardless of whether the try statement completes normally or abruptly (as a result of the method BufferedReader.readLine throwing an IOException).
Prior to Java SE 7, you can use a finally block to ensure that a resource is closed regardless of whether the try statement completes normally or abruptly. The following example uses a finally block instead of a try-with-resources statement:
static String readFirstLineFromFileWithFinallyBlock(String path)
throws IOException {
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally {
if (br != null) br.close();
}
}
Source =>http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
From documentation:
The finally block always executes when the try block exits. This ensures that the finally block is executed even if an unexpected exception occurs.
The runtime system always executes the statements within the finally block regardless of what happens within the try block. So it's the perfect place to perform cleanup.
So it means if you have some connection, stream or some other resources opened you have to be sure that they will be closed after your code block will be executed.
To avoid such ugly blocks you can use utility methods:
public void close(Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (IOException ex) {
// handle block
}
}
}
Since Java 8 (but it is not required) you can provide your own Exception handler with closing resource:
public void close(Closeable closeable, Consumer<? extends Throwable> handler) {
if (closeable != null) {
try {
closeable.close();
} catch (IOException ex) {
handler.accept(ex);
}
}
}
Also, just for knowledge, there are two cases when finally block is not called. It means that in most cases it will be called.
If you are Java 7 or aboveā¦
Don't close in finally block
The close method can throw an IOException and FileInputStream/ObjectInputStream can be null. When you use .close in finally, you must check null and try/catch again.
Use "try-with-resources Statement" instead
Using try-with-resources your code looks like this:
try(
FileInputStream fileIn = new FileInputStream("/tmp/employee.ser");
ObjectInputStream in = new ObjectInputStream(fileIn)
) {
e = (Employee) in.readObject();
// in.close();
// fileIn.close();
}
The try-with-resources syntax guarantees the resources implementing AutoCloseable interface will be closed automatically. So you don't need to call a close method on your code.
You should close connection in finally. As finally always going to execute whether it goes in try or catch.
Also we need to close every connection once it created.
try{
// statements
}catch (){
// statements
}
finally {
in.close();
fileIn.close();
}
I was looking at Java Serialization articles and stumbled a number of times across examples where the streams are closed in the try block instead of in a finally block.
Examples that do it that way are poor examples. While closing a stream within a try block will work for simple one-shot examples, doing this in a case where the code might be executed multiple times is liable to lead to resource leaks.
The other Answers to this Question do a good job of explaining the right way(s) to close streams.
Can someone explain to me why is that?
It comes down to poor quality control on the tutorial sites; i.e. inadequate code reviewing.
The accepted answer certainly has a bug.
The close method can throw an IOException too. If this happens when
in.close is called, the exception prevents fileIn.close from getting
called, and the fileIn stream remains open.
It can implemented as below when multiple streams are involved:
} finally {
if ( in != null) {
try { in .close();
} catch (IOException ex) {
// There is nothing we can do if close fails
}
}
if (fileIn != null) {
try {
fileIn.close();
} catch (IOException ex) {
// Again, there is nothing we can do if close fails
}
}
}
Or, take advantage of Closeable Interface
} finally {
closeResource(in);
closeResource(fileIn);
}
Method:
private static void closeResource(Closeable c) {
if (c != null) {
try {
c.close();
} catch (IOException ex) {
// There is nothing we can do if close fails
}
}
}
You should close in finally block.
It's a bad habit to close in try block.
try {
e = (Employee) in.readObject(); //Possibility of exception
} catch(IOException i) {
} catch(ClassNotFoundException c) {
} finally {
in.close();
fileIn.close();
}
When someone is writing a code by knowing it will throw an exception,he/she has to close the opened resources
You should always close in a finally block.
However, you can use try with resources.
Here's the link: https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
static String readFirstLineFromFile(String path) throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
}
}
Related
I am creating a kind of messenger program, where clients communicate with the server etc.
The problem I have stumbled upon is when trying to create the ObjectInputStream and the ObjectOutputStream. Here is the method that instantiated the object streams:
private void initializeStreams() {
try {
input = new ObjectInputStream(socket.getInputStream());
if (input != null) {
System.out.println("ObjectInputStream successfully initiated");
} else {
System.out.println("ObjectInputStream is null but did not return an exception when being instantiated");
}
} catch (IOException ioe) {
System.out.println("Could not initialize ObjectInputStream: " + ioe.getMessage());
}
try {
output = new ObjectOutputStream(socket.getOutputStream());
if (output != null) {
System.out.println("ObjectOutputStream successfully initiated");
} else {
System.out.println("ObjectOutputStream is null but did not return an exception when being instantiated");
}
} catch (IOException ioe) {
System.out.println("Could not initialize ObjectOutputStream: " + ioe.getMessage());
}
}`
The problem within this method is that NONE of the System.out.println() methods are getting called, even though, at least to my knowledge, one for each of the streams should be getting called. For example, when instantiating the ObjectInputStream, it should either throw an Exception (which it apparently does not because the System.out.println() is not getting called), returning null (which also does not seem to be the case because the System.out.println() is not getting called) or successfully create the ObjectInputStream object, which it does not because the System.out.println() is not getting called. Why does it not run into any of these situations? Am I missing another situation that might occur?
P.S. Yes, the initializeStreams() method is being called from the program, I just checked it putting a System.out.println() at the very first line of the method.
Thank you
Try to write something on the console in the finally-cluster.
What possibly could be is that an exception is thrown, which doesn't get catched.
But you would see that...wouldn't you.
My first tip: Debug your program, that's what often helped me.
But you could also try this:
private void initializeStreams() {
input = null;
output = null;
try {
input = new ObjectInputStream(socket.getInputStream());
}
} catch (IOException ioe) {
System.out.println("Could not initialize ObjectInputStream: " + ioe.getMessage());
}
//just copied the if outside of the try-catch-cluster
if (input != null) {
System.out.println("ObjectInputStream successfully initiated");
} else {
System.out.println("ObjectInputStream is null but did not return an exception when being instantiated");
try {
output = new ObjectOutputStream(socket.getOutputStream());
} catch (IOException ioe) {
System.out.println("Could not initialize ObjectOutputStream: " + ioe.getMessage());
}
if (output != null) {
System.out.println("ObjectOutputStream successfully initiated");
} else {
System.out.println("ObjectOutputStream is null but did not return an exception when being instantiated");
}
}`
Thats one thing I would try in order to find out what or where the problem is.
Even if it doesn't make that much sense ;)
Well, you catch only IOException. There might be RuntimeException for instance in your code. You won't get to your catch block in this case.
Change IOException to Exception and you will see the reason.
new ObjectInputStream() can throw exceptions other than IOException, but your try-catch only captures IOException. What happens if the exception thrown is one of the other types?
Replace IOException with the Exception class which is the parent of all exception classes.Whatever may be the exception,it will surely get caught using Exception class in catch block.
So replace catch (IOException ioe) this with catch (Exception ioe) everywhere in your code.Then u may find where is the exception coming from.
Assuming Java6, is this code safe from file descriptor leak:
{
InputStream in = fileObject.getReadStream();
// fileObject cleans it's internal state in case it throws exception
try {
// do whatever, possibly throwing exception
} finally {
try {
in.close();
} catch (Exception ex) {
// failure to close input stream is no problem
}
}
}
Edit: To make question seem less obvious, to state it other way, is above code equal to this longer code:
{
InputStream in = null;
try {
in = fileObject.getReadStream();
// fileObject cleans it's internal state in case it throws exception
// do whatever, possibly throwing exception
} finally {
if (in != null) {
try {
in.close();
} catch (Exception ex) {
// failure to close input stream is no problem
}
}
}
}
That is, does it matter whether a call to a method which returns opened stream or throws exception is immediately before try, or inside the try block?
Yes, fine. Does not even merit an answer. A variant (I less use) is:
InputStream in = null;
try {
in = fileObject.getReadStream();
// do whatever, possibly throwing exception
} finally {
if (in != null) {
try {
in.close();
} catch (Exception ex) {
// failure to close input stream is no problem if everything else was ok
}
}
}
I'm a student not very familiar with Java, but I wish I can help you a litltle.
I think that the piece of code can't keep you from the problem of file descriptor leak. Though you have let a try clouse wurround the in.close methord, but that won't help if
the in.close method throws some exceptions.
I want to close my stream in the finally block, but it throws an IOException so it seems like I have to nest another try block in my finally block in order to close the stream. Is that the right way to do it? It seems a bit clunky.
Here's the code:
public void read() {
try {
r = new BufferedReader(new InputStreamReader(address.openStream()));
String inLine;
while ((inLine = r.readLine()) != null) {
System.out.println(inLine);
}
} catch (IOException readException) {
readException.printStackTrace();
} finally {
try {
if (r!=null) r.close();
} catch (Exception e){
e.printStackTrace();
}
}
}
Also if you're using Java 7, you can use a try-with-resources statement:
try(BufferedReader r = new BufferedReader(new InputStreamReader(address.openStream()))) {
String inLine;
while ((inLine = r.readLine()) != null) {
System.out.println(inLine);
}
} catch(IOException readException) {
readException.printStackTrace();
}
It seems a bit clunky.
It is. At least java7's try with resources fixes that.
Pre java7 you can make a closeStream function that swallows it:
public void closeStream(Closeable s){
try{
if(s!=null)s.close();
}catch(IOException e){
//Log or rethrow as unchecked (like RuntimException) ;)
}
}
Or put the try...finally inside the try catch:
try{
BufferedReader r = new BufferedReader(new InputStreamReader(address.openStream()));
try{
String inLine;
while ((inLine = r.readLine()) != null) {
System.out.println(inLine);
}
}finally{
r.close();
}
}catch(IOException e){
e.printStackTrace();
}
It's more verbose and an exception in the finally will hide one in the try but it's semantically closer to the try-with-resources introduced in Java 7.
In Java 7 you can do this...
try (BufferedReader r = new BufferedReader(...)){
String inLine;
while ((inLine = r.readLine()) != null) {
System.out.println(inLine);
}
} catch(IOException e) {
//handle exception
}
Declaring a variable in the try block requires that it implements AutoCloseable.
Declaring a variable in the try block also limits its scope to the
try block.
Any variable declared in the try block will automatically have close() called when the try block exits.
It's called a Try with resources statement.
Yes it is clunky, ugly and confusing. One possible solution is to use Commons IO which offers a closeQuietly method.
There's a number of questions in the "Related" column on the right hand of this page that are actually duplicates, I advise to look through these for some other ways of dealing with this issue.
Like the answer mentioning the Commons IO library, the Google Guava Libraries has a similar helper method for things which are java.io.Closeable. The class is com.google.common.io.Closeables. The function you are looking for is similarly named as Commons IO: closeQuietly().
Or you could roll your own to close a bunch like this: Closeables.close(closeable1, closeable2, closeable3, ...) :
import java.io.Closeable;
import java.util.HashMap;
import java.util.Map;
public class Closeables {
public Map<Closeable, Exception> close(Closeable... closeables) {
HashMap<Closeable, Exception> exceptions = null;
for (Closeable closeable : closeables) {
try {
if(closeable != null) closeable.close();
} catch (Exception e) {
if (exceptions == null) {
exceptions = new HashMap<Closeable, Exception>();
}
exceptions.put(closeable, e);
}
}
return exceptions;
}
}
And that even returns a map of any exceptions that were thrown or null if none were.
Your approach within finally is correct. If the code that you call in a finally block can possibly throw an exception, make sure that you either handle it, or log it. Never let it bubble out of the finally block.
Within the catch block you are swallowing the exception - which is not correct.
Thanks...
public void enumerateBar() throws SQLException {
Statement statement = null;
ResultSet resultSet = null;
Connection connection = getConnection();
try {
statement = connection.createStatement();
resultSet = statement.executeQuery("SELECT * FROM Bar");
// Use resultSet
}
finally {
try {
if (resultSet != null)
resultSet.close();
}
finally {
try {
if (statement != null)
statement.close();
}
finally {
connection.close();
}
}
}
}
private Connection getConnection() {
return null;
}
source.
This sample was useful for me.
First thing I noticed in your code is curly bracket { } missing from your code if you look at it. also you need to initialize value of r to null so you need to pass null value to object at first so that if condition you have written can do not null condition check and lets you close the stream.
I need to erase a file in my program. My solution was to have an erase() method that would do that like so:
public static void erase(String string) {
FileWriter fw = null;
try {
fw = new FileWriter(string);
fw.write(new String());
} catch (IOException ie) {
e.printStackTrace();
} finally {
fw.flush();
fw.close();
}
}
Several problems here:
If the fw does not properly initialize (for whatever reason, missing file, invalid persmissions, etc) then when I try to close it in the finally block, there is a NullPointerException.
If I don't have the finally block, then I might be throwing a NullPointerException for the reason above.
If I close the file inside the try block, then I might leak the resource if the file properly opens, but doesn't properly write.
What other problems am I overlooking and how can I harden this method?
You can just wrap the finally functionality in an if-statement:
if(fw != null){
fw.close();
}
This will ensure that if the file was ever opened, then it will be closed. If it wasn't opened in the first place, then it won't do anything, which is what you want.
Also, I'm not sure if it's just like that for posting, but it's generally not advisable to just print a stacktrace in a catch block and continue ("swallowing" the exception). You really should let the exception get thrown because this could hide bugs and make tracking them down very hard.
EDIT: See comment below.
To the best of my knowledge, this is the correct idiomatic way to write your code:
FileWriter fw = new FileWriter(string);
try {
fw.write(new String());
fw.flush();
} catch (IOException ie) {
ie.printStackTrace();
} finally {
fw.close();
}
Explanation:
If new FileWriter() throws an exception, then we don't need to clean up anything. The method exits without executing the finally.
We should put fw.flush() in the try, not in the finally. There are two reasons: If the write failed, then we shouldn't bother flushing. Also, if you put the flush() in finally and it throws an exception, then the close() will be skipped.
Include the flush() in your main block and have only the close() in the catch. Then check for null before closing:
finally {
if(fw!=null) { fw.close(); }
}
With the flush in the main block, you can also try/catch the close and log or ignore any error:
finally {
if(fw!=null) {
try { fw.close(); } catch(Throwable thr) { log.printError("Close failed: "+thr); thr.printStackTrace(); }
}
}
or (not generally recommended):
finally {
try { fw.close(); } catch(Throwable thr) {;}
}
EDIT
The best general Java idiom for handling I/O, IMO, is:
FileWriter fw=null;
try {
fw=new FileWriter(string);
fw.write(new String());
fw.close();
fw=null;
}
catch(IOException ie) {
// do something real here to handle the exception, or don't catch it at all.
}
finally {
if(fw!=null) {
try { fw.close(); } catch(Throwable thr) { thr.printStackTrace(); } // now we're really out of options
}
}
This has the important effect of allowing the catch to catch and handle an exception thrown by close() itself. (The catch clause should only be present if you can handle the exception in some way; do NOT catch and ignore, and generally you should not simply catch and trace.)
Usually, when dealing with Java IO code, here is what I wrote
FileOutputStream out = null;
try
{
out = new FileOutputStream("myfile.txt");
// More and more code goes here...
}
catch (Exception e)
{
}
finally
{
// I put the close code in finally block, to enture the opened
// file stream is always closed even there is exception happened.
if (out != null) {
// Another try catch block, troublesome.
try {
out.close();
} catch (IOException ex) {
}
}
}
As you can see, while I try to close the file stream, I need to deal with another try...catch block.
Look troublesome :(
Is there any way I can avoid? I don't feel comfortable in putting the close code in non-finally block, as exception caused by other codes will make no chance for "close" being called.
It is very important that you close streams in a finally. You can simplify this process with a utility method such as:
public static void closeStream(Closeable closeable) {
if(null != closeable) {
try {
closeable.close();
} catch(IOException ex) {
LOG.warning("Failed to properly close closeable.", ex);
}
}
}
I make it a point of at least logging a stream close failure. The usage then becomes:
FileOutputStream out = null;
try
{
out = new FileOutputStream("myfile.txt");
// More and more code goes here...
}
catch (Exception e)
{
}
finally
{
closeStream(out);
}
In Java 7 I believe that streams will be closed automatically and the need for such blocks should be mostly redundant.
Automatic Resource Management is coming in Java 7 which will automatically provide handling of this. Until then, objects such as OutputStream, InputStream and others implement the Closeable interface since Java 5. I suggest you provide a utility method to safe close these. These methods generally eat exceptions so make sure that you only use them when you want to ignore exceptions (e.g. in finally method). For example:
public class IOUtils {
public static void safeClose(Closeable c) {
try {
if (c != null)
c.close();
} catch (IOException e) {
}
}
}
Note that the close() method can be called multiple times, if it is already closed subsequent calls will have no effect, so also provide a call to close during the normal operation of the try block where an exception will not be ignored. From the Closeable.close documentation:
If the stream is already closed then invoking this method has no effect
So close the output stream in the regular flow of the code and the safeClose method will only perform close if something failed in the try block:
FileOutputStream out = null;
try {
out = new FileOutputStream("myfile.txt");
//...
out.close();
out = null;
} finally {
IOUtils.safeClose(out);
}
Discussion at
Try-catch-finally and then again a try catch
and
Is there a preference for nested try/catch blocks?
basically, the question is whether a close() exception is worth catching.
Project Lombok provides a #Cleanup annotation that removes the need for try catch blocks all together. Here's an example.
I tend to use utility functions for this:
public static void safeClose(OutputStream out) {
try {
out.close();
} catch (Exception e) {
// do nothing
}
}
which changes the code to the slightly more palatable:
FileOutputStream out = null;
try {
out = new FileOutputStream("myfile.txt");
// do stuff
} catch (Exception e) {
// do something
} finally {
safeClose(out);
}
You can't really do much better in Java at least until Java 7 when (hopefully) ARM ("Automatic Resource Management") blocks will help somewhat.
Write a method that looks something like below; call from your finally block...
static void wrappedClose(OutputStream os) {
if (os != null) {
try {
os.close();
}
catch (IOException ex) {
// perhaps log something here?
}
}
Separate your try/catch and try/finally blocks.
try
{
FileOutputStream out = new FileOutputStream("myfile.txt");
try
{
// More and more code goes here...
}
finally
{
out.close();
}
}
catch (Exception e)
{
//handle all exceptions
}
The outer catch will also catch anything thrown by the close.