Core Java
GC with Automatic Resource Management in Java 7
This post provides a brief overview of a new feature introduced in Java 7 called Automatic Resource Management or ARM. The post delves how ARM tries to reduce the code that a developer has to write to efficiently free the JVM heap of allocated resources.
One of the sweetest spots of programming in the Java programming language is automatic handling of object de-allocation. In Java world this is more popularly known as garbage collection; it basically means that developers do not have to worry about de-allocating the object allocated by their code. As soon as a developer is finished with using the object he can nullify all references to the object and then the object becomes eligible for garbage collection.
Garbage collection has a flip side to it however. Unlike in C/C++ where the coder has complete control of memory allocation and de-allocation (malloc, free, new, delete etc), in Java the developer does not have significant control over the process of de-allocation of objects. The JVM manages the process of garbage collecting of unused objects and it is really up to the whims of the JVM when to run a cycle of garbage collection. True, there are method calls like System.gc() or Runtime.getRuntime().gc() that indicates that garbage collection will be run, but these methods merely serve to remind the JVM that -“maybe you need to run a garbage collection now, just a suggestion, no pressure!”. The JVM is fully authorized to disregard such requests and is coded to run garbage collection only when it really sees fit. Hence in practice, developers are always advised not to build their program logic believing System.gc() or Runtime.getRuntime().gc() will trigger a full garbage collection.
There is no denying how much good automatic garbage collection has done to enhance the productivity of developers. However there are some corner cases where garbage collection is not sufficient to mantain a “clean” heap, free of unused objects. Especially if the objects deal with some form of native resources that is served by the underlying operating system. These objects include, but are not limited to IO streams, database connections etc. For these kind of objects developers must release the resources explicitly. Typically these are done through try-catch blocks.
Let us look at a small example that closes an InputStream after finishing the processing of the stream:
InputStream in = null; try { in = new FileInputStream(new File("test.txt"); //do stuff with in } catch(IOException ie) { //SOPs } finally { //do cleanup }
The above looks good and clean; however as soon as we try to close the input stream via in.close() in the finally block, we need to surround it with a try-catch block that catches the checked exception, IOException. Thus the code sample transforms to:
InputStream in = null; try { in = new FileInputStream(new File("test.txt")); //do stuff with in } catch(IOException ie) { //SOPs } finally { try { in.close(); } catch(IOException ioe) { //can't do anything about it } }
Now the above code looks bloated, and with multiple kinds of checked exceptions in different hierarchy, we need more catch clauses. Very soon the code becomes lengthy and difficult to maintain, not to mention the code losing its initial clean and no-nonsense look that even appealed to the eye.
But there is a good news.
Java 7 makes this easier with the new try-catch block. With this feature we can avoid the finally block itself. This is how we do it:
try(InputStream in = new FileInputStream(new File("test.txt")) { //do stuff with in } catch(IOException ie) { //SOPs }
The above block of code will do the cleanup part itself. This is made possible by the introduction of a new interface, java.lang.AutoCloseable which defines a single method, void close() throws Exception. Objects which are subtypes of this interface can be automatically close()d using the above syntax. The above feature is applicable to objects of any class that implement the AutoCloseable interface.
The best part is that even if we initialize multiple AutoCloseable instances in the try() block, it will call the close() method for all the objects, even if some close() method on some object throw any exception.
Coming to the handling of the exceptions, if there was any IOExceptions in our try block as well as in the implicit finally block (where the AutoCloseables are actually being closed), the exception thrown will be the one that was thrown in the try block rather than the one in the implicit finally block.
However we can still have the details of the implicit finally block’s exception from the method Throwable.getSuppressed() which is added as a new method in Java 7.
I think Automatic Resource Management feature, or ARM is a great addition to Java 7.
Happy coding!
Reference: Garbage collection with Automatic Resource Management in Java 7 from our JCG partner Swaranga at the The Java HotSpot blog.
Related Articles :