Tutorial:

New Java 7 Features: The Try-with-resources Language Enhancement

By Sal Pece and Cameron McKenzie

TheServerSide.com

When developing real world, enterprise applications, providing extended functionality means your Java code has to depend upon resources that exist outside of the Java Virtual Machine; this includes anything from a document on the file system, a record in a database, or an open socket on a remote computer. Working with these external goodies in your code means creating Java based objects that represent these resources,  including classes such as the JDBC Connection object, or the File class from the java.io package.

The need for Automatic Resource Management in Java (ARM)

When we interact with external resources, the dance typically follows the same set of steps; that is, we create an instance of the class in question, we open up communication to that resource, we interact with the resource, and finally, the means of communication to that resource is closed. However, while most programmers are very good at opening up and communicating with external resources, one of the embarrassingly recurring themes in Java based development is the fact that closing resources and properly terminating the communication pathway to that resource is a task that is very poorly done. Sadly, many deployed enterprise Java applications create, but do not close, resources like JDBC components or file system objects, resulting in orphaned instances that cannot be properly garbage collected, and external resources that become consumed with the task of managing clients that don't exist. Add on the basic inefficiency this creates for the JVM with regards to memory allocation and clock-cycle consumption, and you'll see how ineffective resource management results in poorly performing applications with difficult to troubleshoot runtime error scenarios.

The java.lang.AutoCloseable interface

To address the problem of programmers leaving far too many heavyweight objects lounging around unclosed on the JVM, the Java 1.7 API has introduced a new interface named java.lang.AutoCloseable which defines a single, simple method to implement.

void close() throws Exception

And part of the magic of the Java 7 release is that any time you use an AutoCloseable resource within a special try-with-resources code block, the close() method will be automatically invoked when the block has finished executing, regardless of whether an exception is thrown during the course of execution.

The try-with-resource syntax

Take a look at this simple little class named OpenDoor which  implements the AutoCloseable interface:

class OpenDoor implements AutoCloseable {
public void close() throws Exception {
System.out.println("The door is closed.");
}
}

Java 7 allows you to create an instance of the AutoCloseable Door class within a special  try-with-resources block:

public class TryWithResources {
public static void main(String[] args) throws Exception {
try (OpenDoor door = new OpenDoor()) {
}
}
}

When this code runs, the close method of the OpenDoor is invoked at the end of the try block, and the output to the console is: "The door is closed.", despite the fact that the close() method of the OpenDoor instance is never explicitly called. As you can see, the close method of the resource is invoked implicitly and automatically, taking the burden or resource management away from the developer.

The syntax simply involved creating or initializing the instance of the AutoCloseable class within round brackets which immediately follow the try; this is known as the resource declaration:

try (OpenDoor door = new OpenDoor()) { }

One thing that might throw Java developers off is the fact that we are using the try keyword without either a catch or a finally block, which wouldn't be valid with prior versions of the JDK. Just remember that when we have a try without a catch or finally block, it is only valid when providing resource declarations after the try. If you tried to write a try block without a catch, finally, or resource declaration, such as this:

try  { }

you would encounter the following compiler problem:

error: 'try' without 'catch', 'finally' or resource declarations

By the way, it should be mentioned that using a resource declaration doesn't mean you can't include a catch or finally block. So long as the resource declaration is used properly, standard rules regarding the use of catch and finally blocks continue to apply, so the following code would be completely valid:

try (OpenDoor door = new OpenDoor()) {
}
catch(Exception e) { } /* do something */
finally { } /* do something else */

Just be aware of the fact that when the catch and finally blocks run, the close method has already been invoked on the AutoCloseable objects listed in the resource declaration.

Declaring multiple resources

Multiple resource declarations are also completely valid. So let's say we added an OpenWindow class into the mix:

class OpenWindow implements AutoCloseable {
public void close() throws Exception{
System.out.println("The window is closed.");
}
}

We could alter the resource declaration by adding a declaration and initialization  for each of these AutoCloseable classes. Note that each additional resource that is listed must be separated by a semi-colon.

try ( OpenDoor door = new OpenDoor(); OpenWindow window = new OpenWindow() ) {
}

Invocation order of AutoCloseable resources

Now, you should be wondering which resource will get closed first when code that lists multiple resources runs. In our example, will the door close first, will the window close first, or is the order indeterminate? 

Take a look at the following code:

public class TryWithResources {


public static void main(String[] args) throws Exception {
try (OpenDoor door = new OpenDoor();
   OpenWindow window = new OpenWindow()) {
}
}
}
class OpenDoor implements AutoCloseable {
public void close() throws Exception{
System.out.println("The door is closed.");
}
}
class OpenWindow implements AutoCloseable {
public void close() throws Exception {
System.out.println("The window is closed.");
}
}

What will be the output of the code above?

a)

The door is closed.
The window is closed.

or b)

The window is closed.
The door is closed.

The answer is b). Resources are closed in the reverse order to which they were created, so the window is closed first, and the door is closed second.

Constructor invocation order in try-with-resource blocks

Of course, don't get confused about the order in which the resources themselves are created. All of the initialization code within the resource declaration is executed in sequential order. Take a look at the following code for example, where we accentuated our OpenWindow and OpenDoor classes with concrete default constructors:

 

public class TryWithResources {


public static void main(String[] args) throws Exception {
try (OpenDoor door = new OpenDoor();
  OpenWindow window = new OpenWindow() ) {
}
catch(Exception e) {}
finally {}
}
}
class OpenDoor implements AutoCloseable {
public OpenDoor() { System.out.println("The door is open.");};
public void close() throws Exception{
System.out.println("The door is closed.");
}
}
class OpenWindow implements AutoCloseable {
public OpenWindow() { System.out.println("The window is open.");};
public void close() throws Exception{
System.out.println("The window is closed.");
}
}

When this class is compiled and executed, the output is:

The door is open.
The window is open.
The window is closed.
The door is closed.

As you can see, the constructors are called in the order in which they appear in the code, while the close methods are invoked in reverse.

Conclusion

All in all, this article covers the basic syntax associated with the automatic resource management features of Java 7, which basically boil down to the use of classes that implement the java.lang.AutoCloseable interface, and the listing of those resources within the new resource declaration part of a try block. By using this new syntax with AutoCloseable resources, you can rest assured that resources will be properly closed, regardless of how execution of the code in a given try block proceeds.

Read the next tutorial in this series: Automatic Resource Management and the AutoCloseable Interface

 

Learning Resources for the Java and Java 7 Certification

OCP Java SE 6 Programmer Practice Exams (Exam 310-065) (Certification Press)
OCP Java SE 7 Programmer Study Guide (Certification Press)
SCJP Sun Certified Programmer for Java 6 Exam 310-065
A Programmer's Guide to Java SCJP Certification: A Comprehensive Primer (3rd Edition)
SCJA Sun Certified Java Associate Study Guide for Test CX-310-019, 2nd Edition

 

Check out these other tutorials from TheServerSide's Sal Pece and Cameron McKenzie covering the new Java 7 features:

New Java 7 Features: Binary Notation and Literal Variable Initialization
New Java 7 Features: Numeric Underscores with Literals Tutorial
New Java 7 Features: Using String in the Switch Statement Tutorial
New Java 7 Features: The Try-with-resources Language Enhancement Tutorial 
New Java 7 Features: Automatic Resource Management (ARM) and the AutoCloseable Interface Tutorial
New Java 7 Features: Suppressed Exceptions and Try-with-resources Tutorial
Java 7 Mock Certification Exam: A Tricky OCPJP Question about ARM and Try-with-Resources
OCAJP Exam to Debuts in March 2010. OCPJP Released in June?
OCPJP & OCAJP Java 7 Exams: Oracle Drops the Training Requirement
OCAJP and OCPJP Changes for Java 7:  New Objectives, a Format Change and a Price Hike

29 Dec 2011

Related Content

Related Resources