try-with-resources

Java 7 gave us try-with-resources, a nice feature on exception handling. This tutorial is part 3 of the exception handling series. Part I is about basics of exception handling. Part II is about exception hierarchy, stack traces, handling exception and best practices. Now in this part three of exception handling tutorial, we will see about try-with-resources (ARM) introduced in Java version 7.

Close the resources in finally block is a well know rule for all java developers. As part of exception handling mechanism, we should always ensure to close and release the resources that is used inside the block. In a block of code which is enclosed in a try-catch block, if an exception is thrown the normal flow is altered.

try {
	//code statements
	//exception thrown here
	//lines not reached if exception thrown
} catch (Exception e) {
	//lines reached only when exception is thrown
} finally {
	//always executed
	//irrespective of an exception thrown or not
}

Look at the above code block. The best place to close and release all the resources is finally block. So what is the resource we are talking about here? Resources means database connection, file connections, etc.

Auto Close

Poor Structure

As stated above, we are going to close the resources in the finally block. Look at the following code, how ugly it looks like.

...
InputStream is = null;
try {
	is = new FileInputStream("test");
	is.read();
	...
} catch (Exception e) {
	...
} finally {
	try {
		is.close();
	} catch (IOException e) {
		e.printStackTrace();
		...
	}
}

Explicitly the programmer has to close the resource and need to surround it with a try-catch block and all inside the finally. This is a standard repeated code in java projects.

We just need to put a try-catch and we don’t do anything to handle it there. Apache’s IOUtils introduced methods to use inside finally block such as above.

org.apache.commons.io.IOUtils has methods to suppress the exception thrown inside finally block when the close method is executed.

public static void closeQuietly(InputStream input)

Ads by Google

Automatic Resource Management (ARM)

In Java 7, we got a nice feature to manage these resources automatically. Manage is really a hype word here, all it does is close the resources. Automatic resource management, helps to close the resources automatically.

Resource instantiation should be done within try(). A parenthesis () is introduced after try statement and the resource instantiation should happen within that paranthesis as below,

try (InputStream is = new FileInputStream("test")) {
	is.read();
	...
} catch(Exception e) {
	...
} finally {
	//no need to add code to close InputStream
	//it's close method will be internally called
}

try-with-resources and AutoCloseable

  • All the classes cannot be used in try-with-resources. AutoCloseable is an interface used as a contract to implement try-with-resources. Classes that implements AutoCloseable must be used as a resource in try-with-resources, else we will get compilation error.
  • close is the only method in AutoCloseable and it gets automatically invoked at runtime.
  • Multiple classes can be declared within the same try as “try (Lion lion = new Lion(); Tiger tiger = new Tiger()) {…”
  • During initialization of multiple resources in ‘try’, if there is any issue then immediately in the reverse order those resources that are already initialized will be closed.
  • When multiple classes are used in ‘try’, then the close method is called in the reverse order. To understand this, check the below example.
  • try-with-resources, can have catch and finally. They work as usual and no change in it.
  • In try-with-resources on exception, before going to catch the close statements will be executed.
  • While implementing AutoCloseable, best practice is to throw specific exception and not the highest level ‘Exception’ itself. This needs to highlighted because the signature of ‘close’ in AutoCloseable throws Exception.
  • On implementation, AutoCloseable.close should not throw InterrupedException, because at runtime if this exception is suppressed it will cause issues in thread handling.
  • By specification this close method is not required to be idempotent. But still, it is best practice to implement it as idempotent. That is, even if the close method is invoked multiple times, it should act as same.
  • Closeable is an interface that extends AutoCloseable and its close method must be idempotent.
  • Resource declared in try gets instantiated just before the start of the try-block.
  • Resource is implicitly declared as final.

Custom Implementation of AutoCloseable

Let us create a custom class that implement AutoCloseable. It is not rocket science, there is only one method named ‘close’ in the interface and implementing that is sufficient.

Lion.java

package com.javapapers.exceptionhandling;

public class Lion implements AutoCloseable {
	public Lion() {
		System.out.println("LION is OPEN in the wild.");
	};

	public void hunt() throws Exception {
		throw new Exception("DeerNotFound says Lion!");
	}

	public void close() throws Exception {
		System.out.println("LION is CLOSED in the cage.");
		throw new Exception("Unable to close the cage!");
	}
}

Tiger.java

package com.javapapers.exceptionhandling;

public class Tiger implements AutoCloseable {
	public Tiger() {
		System.out.println("TIGER is OPEN in the wild.");
	};

	public void hunt() throws Exception {
		throw new Exception("DeerNotFound says Tiger!");
	}

	public void close() throws Exception {
		System.out.println("TIGER is CLOSED in the cage.");
	}
}

TryWithResourcesExample.java

package com.javapapers.exceptionhandling;


public class TryWithResourcesExample {

	public static void main(String[] args) {
		try (Lion lion = new Lion(); Tiger tiger = new Tiger()) {

			lion.hunt();
			tiger.hunt();

		} catch (Exception e) {
			System.out.println(e);
		} finally {
			System.out.println("Finally.");
		}
	
	}
}

Output for above example:

  1. LION is OPEN in the wild.
  2. TIGER is OPEN in the wild.
  3. TIGER is CLOSED in the cage.
  4. LION is CLOSED in the cage.
  5. java.lang.Exception: DeerNotFound!
  6. Finally.

Look at the sequence of output listed above to understand the flow of control and the order in which the close method is invoked internally.

Throwable.getSuppressed Exceptions

Read the Lion and Tiger example line by line. There is an important point to understand is hidden in it. Now go back and read Lion.java

public void close() throws Exception {
	System.out.println("LION is CLOSED in the cage.");
	throw new Exception("Unable to close the cage!");
}

  • Lion’s close throws an exception, but where is it in the output? It got suppressed. That is the concept of try-with-resources.
  • If an exception is thrown in the try block, then the control will be transferred to catch. In between the jump to catch block the close() will be internally invoked for the registered resources.
  • Inside the close(), there is a possibility for an exception while closing the resource. If an exception is thrown (as given in Lion example), then it will be suppressed and the exception that is thrown in the try block (before calling close), will be exposed.
  • So how do we know about the suppressed exception? Here you go, use the Throwable.getSuppressed get the exceptions that are suppressed in try-with-resources.
  • If there are multiple resources to be closed and an exception is thrown during closing of one exception, irrespective of that all the resources will be closed.

When try-with-resources compiled to bytecode…

As given in Java Language Specification,

try (VariableModifiersopt R Identifier = Expression ...)
    Block

following is the equivalent code of above, when converted to without try-with-resources,

{
    final VariableModifiers_minus_final R Identifier = Expression;
    Throwable #primaryExc = null;

    try ResourceSpecification_tail
        Block
    catch (Throwable #t) {
        #primaryExc = #t;
        throw #t;
    } finally {
        if (Identifier != null) {
            if (#primaryExc != null) {
                try {
                    Identifier.close();
                } catch (Throwable #suppressedExc) {
                    #primaryExc.addSuppressed(#suppressedExc);
                }
            } else {
                Identifier.close();
            }
        }
    }
}

This Core Java tutorial was added on 17/02/2013.

«

»

Comments on "try-with-resources"

  1. dheeraj says:

    THNAK U FOR THIS WONDERFUL KNOWLEDGE…..

  2. Chaula Ganatra says:

    Very well explained.
    Thanks Joe.

  3. samir says:

    Thanks for the nice explanation.

  4. Andrew says:

    Hey Joe,

    Thanks for a nice tutorial about try-with-resources statement!
    The only thing I would add is a word of caution regarding chaining resources like:

    try (Reader reader = new BufferedReader(new FileReader(“file”))) {
    // …
    }

    Such a pattern can be dangerous under certain circumstances.
    I wrote about this here: http://ayp-sd.blogspot.com/2014/01/java-7-try-with-resources-statement.html

  5. jagnya says:

    thank u sir………

  6. abhi says:

    Hi Joe,

    Thanks for the tutorial. One output line seems missing, i.e.
    “java.lang.Exception: DeerNotFound says Lion!”

    I know it is obivious,but just to avoid any confusion. Thanks.

    Also,can you please add some Java Spring(frameworks) tutorial etc. Thanks in advance.

  7. great tutorial, thanks for sharing.

  8. Ravi says:

    Sounds good..

  9. Venkat says:

    Nice explanation….

  10. Ragav says:

    Very informative.. :)

  11. amit sarang says:

    thax joe.

    nice to learn from u. whatever read upto now from ur blog always interesting and informativ. i like to read ur blog rather than book.

  12. Varshu says:

    HI Joe,

    Your blog provides lot of good information. This is nice feature in Java 7. Thanks for bringing it in notice.

  13. Chirag Moradiy says:

    Well explained!!

    It is the must-use feature which I wasn’t using so far though my projects run on jdk7. I will definitely use this feature and suggest my team to do the same.

    Thanks for giving us your valuable time in writing this article.

  14. Raj says:

    It’s really good…..

  15. Neha says:

    Nice article. Well explained!

  16. Shiva says:

    Good one….

  17. Abimaran says:

    Thank, it was nice!

  18. atf says:

    DO YOU HAVE CODE FOR GETTING THE REMOTE IP ADDRESS ON SAME NETWORK(LAN) IN JAVA
    PLZ GIVE

  19. Rakesh says:

    Nice explanation..But one question, how to add customly created exceptions to be suppressed.

  20. sailu says:

    its a fantastic article joe..simple and informative

  21. Anonymous says:

    Thanks for sharing you knowledge with us.

    SOoo Nice of you.

  22. sudha says:

    A great post and u explained it very beautifully..Thanks for sharing your knowledge with us. Keep it up.

  23. Ajay says:

    good explainations…

  24. pradip garala says:

    nice work…

  25. Renuka says:

    informative

  26. suneetha says:

    Not BAd

  27. Yatheesh says:

    very nice

  28. Dharmveer says:

    Thanks a lot for this well explained article…

  29. Praveen S M says:

    Good one..

  30. [...] Yes, this exception handling tutorial series is not complete yet and continue reading the part III of exception handling series try-with-resources. [...]

Your Comment