Mr. Nicky
Mr. Nicky

Reputation: 1669

Java Serialization: close streams in try or in a finally block?

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

Upvotes: 3

Views: 10461

Answers (8)

myx4play
myx4play

Reputation: 131

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.

Upvotes: 2

Vivek Pratap Singh
Vivek Pratap Singh

Reputation: 9974

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
  }
 }
}

Upvotes: 1

user6503581
user6503581

Reputation:

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();
  }
}

Upvotes: 0

Stephen C
Stephen C

Reputation: 719336

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.

Upvotes: 1

Andrii Abramov
Andrii Abramov

Reputation: 10773

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.

Upvotes: 2

Roushan
Roushan

Reputation: 4440

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

Upvotes: 7

Prasanna Kumar H A
Prasanna Kumar H A

Reputation: 3431

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

Upvotes: 0

Palak Nagar
Palak Nagar

Reputation: 52

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();
}

Upvotes: 1

Related Questions