Java AutoCloseable : How does it work?

Most of us know that AutoCloseable is an interface that a class needs to implement to ensure that resources are automatically released. Let us consider a very simple example:

public class MyResource implements AutoCloseable{
    
	public void openConnection(){
		System.out.println("Opening expensive resource...");
	}
	
	public static void main(String args[]) throws Exception{
		
		MyResource myResource = new MyResource();
		myResource.openConnection();
	}

	@Override
	public void close() throws Exception {
		System.out.println("Releasing expensive resource...");		
	}
}

The output from this is simply :

Opening expensive resource…

The close method was never called.

AutoCloseable – Automatic Resource Management ?

We kind of assumed that implementing the AutoCloseable interface will magically do everything for us. Isn’t this feature also called Automatic Resource Management ? I think the automatic word can be a little misleading here.May be that is why this feature is also called try-with-resources. Well, as a programmer, I do forget things.

What we have clearly forgotten is to wrap the resource in a try block. If you read the java docs (which can be a bit boring at times), it is clearly mentioned that the resource needs to be wrapped in a try block. But I am sure we don’t really read the java docs that carefully. Most IDE’s now days show us a warning that the resource is never closed. Having said that, let us take a look at the byte code

public static void main(java.lang.String[]) throws java.lang.Exception;
Code:
0: new #5 // class blog/MyResource
3: dup
4: invokespecial #6 // Method “<init>”:()V
7: astore_1
8: aload_1
9: invokevirtual #7 // Method openConnection:()V
12: return

On line 9 , there is a  invokeVirtual call to openConnection method and really nothing about the call to close method. There is a return after a call to the openConnection method.

Try block to the rescue

Let us go ahead and wrap the resource in a try block.

public class MyResource implements AutoCloseable{
    
	public void openConnection(){
		System.out.println("Opening expensive resource...");
	}
	
	public static void main(String args[]) throws Exception{
	
		try(MyResource myResource = new MyResource()){
			myResource.openConnection();	
		}
	}

	@Override
	public void close() throws Exception {
		System.out.println("Releasing expensive resource...");		
	}
}

This time the output is as expected:

Opening expensive resource…
Releasing expensive resource…

So putting a try around the resource did invoke the close method. But to understand this, let us take a look at the byte code:

public static void main(java.lang.String[]) throws java.lang.Exception;
Code:
0: new #5 // class blog/MyResource
3: dup
4: invokespecial #6 // Method “<init>”:()V
7: astore_1
8: aconst_null
9: astore_2
10: aload_1
11: invokevirtual #7 // Method openConnection:()V
14: aload_1
15: ifnull 85
18: aload_2
19: ifnull 38
22: aload_1
23: invokevirtual #8 // Method close:()V
26: goto 85
29: astore_3
30: aload_2
31: aload_3

See line number 23 above. The compiler inserts the call to the close method after the openConnection method. This is done using invokeVirtual instruction.

Conclusion

If you implement the AutoCloseable interface and have an expensive resource which should be closed, remember to wrap the resource in a try block.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: