Starting in JDK 9 build 54, compiler support for private interface methods have been resurrected. This was one feature that was planned for Java 8 and did not make the final cut. It is now part of JEP 213. The primary motivation for this proposal is to enable code sharing between non abstract methods in an interface.

Interface evolution was always a tricky problem to solve in earlier versions of Java. You either need to maintain multiple versions of APIs which creates a technical debt over time or brute force your clients to accommodate new methods which breaks binary compatibility. The need to enhance an interface needed support in interface themselves instead of resorting to other options. This was fulfilled by default methods in interfaces in Java 8. Taking this further, private methods come in handy when we have a reusable block of code that default methods could benefit from. Latest Intellij 14.1 builds started to support JDK 9, so lets code an interface!.

An interface now can contain these:

– constants
– method signatures
– nested types
– default methods (since 1.8)
– static methods (since 1.8)
– private methods (since 1.9)
– private static methods (since 1.9)

Some of the restrictions of private methods include:
– private methods must contain method body
– combination of modifiers not allowed : abstract and private
– private methods in an interface does not disqualify it from being a @FunctionalInterface
– annotations types cannot declare private methods
– name clash not permitted

– cannot reduce visibility of private methods

Possibly Related Posts:


Java 8 adds support for bulk data operations (JEP 107) in the Collections library. It is unlikely every forms of bulk data operations will be added to the retrofitted Collections framework, but the language designers are making every possible effort in accommodating general use cases of “filter/map/reduce for Java”. Libraries should make use of parallelization on multi-core platforms in order to perform massive parallelizable operations and this means literally kicking-in your cores to its fullest potential. This area of OpenJDK is undergoing heavy changes, it is possible these APIs are changed or improved before milestone 6 when JDK 8 is officially feature complete. But, they are stable enough to give it a spin today. You can grab the lambda build from here. I have been using the latest Intellij 12 preview for my hands on with the new features in Java 8. It actually supports most of the new Java 8 languauge features and intellisense rocks.

The Streams proposal is well thought of and brings the much sought after functional power to Java and you won’t regret upgrading from Java 6 -> Java 8, if you are still hanging around with Java 6 in that time frame. This one is just a preview of what is coming in Java 8.

Let us implement a method to check if a keyword list exists in a tweet. Here is one way to implement it in plain old Java.

Now, that I am taking the Functional programming course, I would like to compare it with Scala, the mature functional language on the JVM. In Scala, this can be implemented as one liners and there are couple different ways to do this, one using exists and other using the foldLeft function, although exists is my favorite as it is clean and less cryptic.

I can understand why functional programmers are more obsessed with “small is beautiful” theme and hate outright verbosity. Now that all dust has settled with Java’s once uncertain future and stalled innovation, its new steward Oracle is betting on to bring back its lost glory in round 2 and you see that happening with Java 8. Finally, the language brings freshness to Java camp in offering functional constructs to Java and make functional programming in Java a breeze. Here is a teaser:

Isn’t nice to have a one liners in Java too? Java is close, but could reduce some noise as you have to call stream() on the Collection which might seem unnecessary. Stream interface supports a fold operation very similar to Scala’s foldLeft function and implements using a similar approach as of Scala.

Now, let us take this example further, filter tweets matching keywords. This was inspired by Week 3 assignment from the “Functional Programming Principles in Scala” course which btw I am enjoying it so far. Again, you can see Java makes it a cut. I am trying to keep it not being a spoiler.


In this example, you notice that you have to use stream() as well as into() operations to get the result of stream processing. I believe this is a limitation with the iteration 2 Streams implementation which was referred as “the bun problem” that we have to live with.

Streams in Java 8 is making implementing bulk operations a no brainer. While it involves some effort in learning the new concepts, it opens up a new dimension to library developers. Thanks to JSR 335 which brings Java up to speed with other cool languages out there in the planet.

For fun, I want to toss in a new exists() API to the Stream interface so I could use it to filter on my keywords list. This can be done with the help of extension methods, another new concept in Java 8.


Basically, I am delegating the implementation to anyMatch() for simplicity as both reveal the same purpose. Here is a custom List implementation that exposes this API on the collection. This is a primitive implementation, which btw I am trying to keep this updated with the recent library changes. I hope there is a better way to do this, but the point is, it enables developers to extend the Streams framework and fill in special cases.

exists() variant of the code is shown below.


There are several new concepts in the library that requires functional mindset to fully benefit from it. You can switch these Streams to use a parallel version, by using parallel() instead of stream() on the Collection. Stream operations are classified as lazy and eager based on their implementation.
I hope to uncover some of these new concepts in the coming months. I wish function types made into Java 8, but that is different story for another day. Enjoy functional programming in Java!

I have covered Lambdas in the past and this excellent JavaZone talk by Angelika Langer should bring you up to speed with the current state of affairs with Lambdas in Java 8. You can also find Maurice Naftalin’s LambdaFAQ useful.

Lambdas in Java 8 from JavaZone on Vimeo.

Update (10/20/2012) : Updated samples to use method reference and built with the latest Lambda build 61. Clarified the bun-problem with streams proposal.
Update (11/20/2012) : Updated MyList implementation to compile with the latest API changes and much cleaner implementation.
Update (2/3/2013) : Updated code to compile with the latest lambda build 75.
Update (6/15/2013) : Updated code to compile with the latest lambda build 94.

Possibly Related Posts:



Last week, JetBrains announced their new statically typed language Kotlin at the JVM Language Summit. Kotlin joins the elite group of statically typed languages : Scala, Gosu, Ceylon, Fantom, targeted to run on the JVM. Scala is the most mature in this statically typed landscape. Fantom supports static and dynamic typing, so it may not be directly competing with others. Both Ceylon and Kotlin are not publicly available yet, but the documentation can give you a preview of how these languages shape up. Kotlin definitely has the potential to attract Java developers due to its backing from the leading Java IDE maker. The good news is Kotlin will debut with an IDE support from day one, but this keeps expectations high on this project.

While Kotlin and Ceylon try to score on the “complexity attribute” of its mature competitor Scala, it may very well become a competitor to Java 8 from an adoption perspective. Java 8 will include support for the most sought after language feature Lambda is slated for late 2012 release. Both Ceylon and Kotlin plans to support higher order functions among others may have stable releases around that time frame. As these young languages are work in progress, it provides an excellent opportunity for them to receive constructive critique from the community and possibly fix or clarify their design choices. Given some of the features that could be implemented as compiler plugins in Kotlin makes it a perfect candidate for experimenting advanced language constructs that were once alien to Java.

Can Kotlin attract Java developers?

Well, it certainly has the potential to attract Java developers and you can already see huge interest from the developer community (Kotlin language documentation is already flooded with feedback) trying to understand what Kotlin can bring to the rapidly innovating JVM platform languages. Some blogs debate its cool new features and its approach to becoming the next big JVM language (NBJL). In addition to the cool features it plans to support, Kotlin incorporates some good idioms from Josh Bloch’s Effective Java. The language documentation references at least 10+ idioms from Effective Java which shows its commitment to adopting best practices that aid developer productivity and program maintainability. Here are some of those idioms highlighted in Kotlin documentation:

Item 11: Override clone judiciously
Item 14: In public classes, use accessor methods, not public fields
Item 16: Favor composition over inheritance
Item 17: Design and document for inheritance or else prohibit it
Item 18: Prefer interfaces to abstract classes
Item 23: Don’t use raw types in new code
Item 24: Eliminate unchecked warnings
Item 25: Prefer lists to arrays
Item 28: Use bounded wildcards to increase API flexibility
Item 38: Check parameters for validity
Item 43: Return empty arrays or collections, not nulls
Item 65: Don’t ignore exceptions
Item 69: Prefer concurrency utilities to wait and notify

Kotlin documentation by far is the most comprehensive source of information about the language and its syntax and it is well maintained. Once again JetBrains folks hit the right chord as the documentation is crucial for any language adoption early on. I do believe JetBrains would continue to deliver its promise of “Develop With Pleasure” with Kotlin too. So far, I have liked Kotlin’s approach to becoming the NBJL and its rich feature set and expressive syntax undoubtedly makes it a compelling choice for developers alike.

Possibly Related Posts:


One of the primary uses of Lambda expressions is to implement aggregate operations that can often be parallelized using multi-core processors we have today. The computation over bulk data structures is an area where Lambda expressions provide much needed support where part of the computation is caller defined. Doug Lea’s JSR166y Concurrency interest group exactly brings these rich set of Collections that supports parallel operations to perform bulk computation over data in the Java platform.

Let us look at an aggregate operations example using a ParallelArray, that maintains a ForkJoinPool and an array in order to provide parallel aggregate operations. The jsr166y package is already included in Java 7 as part of the ForkJoin framework. The extra166y package that contains Collections supporting parallel operations is not part of the JDK yet, but you should be able to use them today as an add-on library.

import extra166y.Ops;
import extra166y.ParallelArray;
import extra166y.ParallelDoubleArray;

public class AggregateOpsExample {

    ParallelArray<Student> students;

    public AggregateOpsExample() {
        jsr166y.ForkJoinPool fjPool = new jsr166y.ForkJoinPool();
        // Create a "fictional" Student array
        Student s1 = new Student("S1", 2010, 85, 5);
        Student s2 = new Student("S2", 2010, 91, 4);
        Student s3 = new Student("S3", 2010, 95, 3);
        Student[] data = new Student[]{s1, s2, s3};
        students = ParallelArray.createFromCopy(new Student[]{s1, s2, s3}, fjPool);
    }

    public Student getStudent(int index) {
        return students.get(index);
    }

    public double getMaxSeniorGpa() {
        return students.withFilter(isSenior)
        			   .withMapping(gpaField)
        			   .max();
    }

    public ParallelDoubleArray.SummaryStatistics getSummaryStatistics() {
        return students.withFilter(isSenior)
	                   .withMapping(gpaField)
        	           .summary();
    }

    // helpers:
    static final class IsSenior implements Ops.Predicate<Student> {
        public boolean op(Student s) {
            return s.credits > 90;
        }
    }

    static final IsSenior isSenior = new IsSenior();

    static final class GpaField implements Ops.ObjectToDouble<Student> {
        public double op(Student s) {
            return s.gpa;
        }
    }

    static final GpaField gpaField = new GpaField();

    public static void main(String[] args) {
        AggregateOpsExample test = new AggregateOpsExample();
        double bestGpa = test.getMaxSeniorGpa();
        System.out.println("Best GPA : " + bestGpa);
        ParallelDoubleArray.SummaryStatistics summary = test.getSummaryStatistics();
        System.out.println("Last Best Student: " + test.getStudent(summary.indexOfMin()).name);
        System.out.println("Average GPA in class of 2010 : " + summary.average());
    }

    public class Student {
        String name;
        int graduationYear;
        int credits;
        double gpa;

        public Student(String name, int graduationYear, int credits, double gpa) {
            this.name = name;
            this.graduationYear = graduationYear;
            this.credits = credits;
            this.gpa = gpa;
        }
    }
}

In Line#10, a ForkJoinPool is created with parallelism equal to Runtime.availableProcessors(), in my case 2. Lines 24-26 and 30-32 perform aggregate operations on Students array. These operations take advantage of multi-core processors than the traditional sequential approach we used to filter and map a collection. By introducing Lambda expressions in the client code, you can remove much of the boilerplate in lines 36-50 in our code.

Let us build upon the above example to time these aggregate operations and erase some of the boilerplate using Lambda expressions.

import extra166y.Ops;
import extra166y.ParallelArray;
import extra166y.ParallelDoubleArray;

public class TimedAggregateOps {

	ParallelArray<Student> students;

	public TimedAggregateOps() {
		jsr166y.ForkJoinPool fjPool = new jsr166y.ForkJoinPool();
        // Create a "fictional" Student array
		Student s1 = new Student("S1", 2010, 85, 5);
		Student s2 = new Student("S2", 2010, 91, 4);
		Student s3 = new Student("S3", 2010, 95, 3);
		Student[] data = new Student[]{s1, s2, s3};
		students = ParallelArray.createFromCopy(new Student[]{s1, s2, s3}, fjPool);
	}

	interface Block {
		public void execute();
	}

	static void time(boolean maxGpa, Block block) throws Exception {
		long startTime = System.nanoTime();
		boolean success = true;
		try {
			block.execute();
		} catch (final Throwable ex) {
			success = false;
			throw ex;
		} finally {
			recordTiming(maxGpa, System.nanoTime() - startTime, success);
		}
	}

	static void recordTiming(boolean maxGpa, long nanoseconds,  boolean succeeded) {
		if (maxGpa) {
			System.out.println("maxGpa took " + nanoseconds + "ns and operation " + (succeeded ? "succeeded." : "failed."));
		} else {
			System.out.println("avgGpa took " + nanoseconds + "ns and operation " + (succeeded ? "succeeded." : "failed."));
		}
	}

    static final Ops.Predicate<Student> isSenior = #{s -> s.credits > 90};
    static final Ops.ObjectToDouble<Student> gpaField = #{s -> s.gpa};

    public void findMaxSeniorGpa() {
        double maxGpa = students.withFilter(isSenior)
        						.withMapping(gpaField)
        						.max();
        System.out.println("Maximum GPA : " + maxGpa);
    }

    public void findAverageGpa() {
        ParallelDoubleArray.SummaryStatistics summary = students.withFilter(isSenior)
                												.withMapping(gpaField)
                												.summary();
		double avgGpa = summary.average();
		System.out.println("Average GPA : " + avgGpa);
    }

	void test(boolean maxGpa) throws Exception {
		try {
			time(maxGpa, #{
				if (maxGpa)
					findMaxSeniorGpa();
				else
					findAverageGpa();
			});
		} catch (final Throwable t) {
			throw t;
		}
	}

	public static void main(String[] args) throws Exception {
		TimedAggregateOps tao = new TimedAggregateOps();
		tao.test(true);
		tao.test(false);
	}
}

The client code that consumes this parallel Collections library has become more concise and removes much of the boilerplate with the use of Lambda expressions. Lines 36-50 in the earlier example is reduced to Lines 44-45 in this example. When these libraries take advantage of Lambda expressions, implementations would become powerful and more efficient. For example, much of the today’s verbose APIs such as map, reduce, filter defined in ParallelArray class would benefit from executing block of code using Lambda expressions. I recommend watching Closures Cookbook JavaOne 2008 presentation from Neal Gafter.

You can run this example using the prototype compiler that supports Lambda expressions. The batch scripts used in my original post should be updated to include JSR166y libraries in classpath, which you could download from JSR-166 maintenance website.

javac.bat

@echo off
C:\jdk1.7.0\bin\java.exe -cp classes.jar;jsr166y.jar;extra166y.jar com.sun.tools.javac.Main %1

java.bat

@echo off
C:\jdk1.7.0\bin\java.exe -cp classes.jar;.;jsr166y.jar;extra166y.jar %1

Possibly Related Posts:


Recently, Brian Goetz published modified draft of the Lambda proposal. This draft is mature in terms of the direction where Lambda is heading for in the Java world and introduces some breaking changes from earlier draft to align with this direction. While there are few things that need to be sorted out, this draft is simple to understand, unlike the earlier proposals we have seen. Last week, Maurizio pushed an updated prototype that aligns with this new draft.

Lambdas (originally knows as Closures) are available in the form of anonymous inner classes in Java. Anonymous inner classes are a form of nested classes that has no name and exhibits the following behavior as detailed in JLS 15.9.5.

  • An anonymous class is never abstract
  • An anonymous class is always an inner class; it is never static
  • An anonymous class is always implicitly final

One common use of anonymous inner classes is to create function objects in Java on the fly. [Refer Item 21 in Effective Java 2nd Edition pg 103]

Let us look at sorting an array of strings based on its length using an anonymous Comparator instance.

        String[] teams = {"Violet", "Indigo", "Blue", "Green", "Yellow", "Orange", "Red"};
        Arrays.sort(teams, new Comparator<String>() {
            @Override
            public int compare(String s1, String s2) {
                return s1.length() - s2.length();
            }
        });

To create process objects, such as Runnable, Thread, or TimerTask instances.

        final ExecutorService executor = Executors.newCachedThreadPool();
        executor.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("Processing a short-lived asynchronous task.");
            }
        });

Anonymous classes have many limitations as outlined in Item 22 in Effective Java 2nd Edition [pg 108]. With Lambda expressions, you should be able to rewrite these samples more concisely eliminating the bulky syntax that comes with anonymous inner classes :

        final ExecutorService executor = Executors.newCachedThreadPool();
        // assignment context
        Runnable task = #{ System.out.println("Processing a short-lived asynchronous task.") }; //take1
        executor.submit(task);
        // cast target context
        task = (Runnable)#{System.out.println("Processing a short-lived asynchronous task.")}; //take 2
        executor.submit(task); 
        // method invocation context
        executor.submit((Runnable)#{System.out.println("Processing a short-lived asynchronous task.")}); //take 3

Array sorting using a comparator with Lambda expressions is a one liner:

	String[] teams = {"Violet", "Indigo", "Blue", "Green", "Yellow", "Orange", "Red"};
	final Comparator<String> c = #{s1, s2 -> s1.length() - s2.length()};
	Arrays.sort(teams, c); //take1
	Arrays.sort(teams, #{s1, s2 -> s1.length() - s2.length()}); //take 2

So, what next? Let us do some hands-on with these Lambdas and explore what Lambdas has to offer for Java developers. I setup the new prototype on my Windows environment following Remi’s instructions. It was fairly straight forward (all you need is Mercurial Client, Apache Ant, and latest JDK 7 build).

Here is a simple build script (build.bat) I used in Windows, that you can place in the “make” sub-directory under “langtools” :

ant -Dboot.java.home=C:\jdk1.7.0 clean build

This would create classes.jar under “dist\lib” sub-directory. You need to place this jar in your classpath when using the prototype.

You can use the following batch scripts for compiling and running your Lambda examples. I tested with the recent JDK 7 build (b115).

javac.bat

@echo off
C:\jdk1.7.0\bin\java.exe -cp classes.jar com.sun.tools.javac.Main %1

java.bat

@echo off
C:\jdk1.7.0\bin\java.exe -cp classes.jar;. %1

It is required to include classes.jar in the classpath due to runtime dependencies that are not available in the binary build. To make sure if you are running the prototype compiler, the output should show “internal” tag:

C:\JDK7\lambda\samples>javac.bat -version
javac 1.7.0-internal

Let us look at a simple example:

public class SimpleLambda {
	abstract class HelloWorld {
		abstract void greet();
	}
	{
		HelloWorld greeting = #{ System.out.println("Hello World!") };//nilary Lambda expression
		greeting.greet();
	}
	public static void main(String[] args) {
		new SimpleLambda();
	}
}

To compile this example:

javac.bat SimpleLambda.java

To run this example:

java.bat SimpleLambda

Voila, you ran your first lambda example successfully if you see “Hello World!” output.

Let us look at another example which uses parameterized types in this case.

	interface Squarer<X, Y> {
		Y square(X x);
	}
	{
		Squarer<Integer, Integer> s = #{ Integer x -> x * x };// 1-ary Lambda expression
		System.out.println(s.square(5));
	}

In both these examples, you notice a pattern commonly referred to as single abstract method (SAM), defined using an interface or an abstract class with exactly one abstract method. This is a structural property identified by the compiler and it does not take into account methods inherited from java.lang.Object (as in java.util.Comparator).

For example, Runnable, Callable, etc belongs to this category of SAM types that can be converted in the context of assignment as shown below.

final Runnable task = #{ System.out.println(“Processing a short-lived asynchronous task.”) };

In this code, “task” is an Runnable instance, while the lambda expression #{…} is not. Only after conversion, the target type becomes an instance of that SAM type.

Syntax – The Holy Grail of Lambda


Lambda expressions begin with ‘#’ special character and an arrow token ‘->’ is used to separate the formal parameters from the body of the Lambda. In case of single line Lambda expression, return keyword and trailing semicolon can be omitted. For nilary Lambda expression, the arrow token can be omitted.

Lambdas in Java exhibit the following behavior :

  • An interface, or abstract class, with exactly one abstract method are referred to as a SAM types.
  • Lambdas are not instances of classes.
  • Lambdas are converted to SAM types.
  • SAM types are instances of classes.
  • Lambdas are lexically scoped.

Lambda definition (excerpt from draft)

A lambda expression e is convertible-to a SAM type S if an anonymous inner class that is a subtype of S and that declares a method with the same name as S’s abstract method and a signature and return type corresponding to the lambda expressions signature and return type would be considered assignment-compatible with S.

The return type and exception types of a lambda expression are inferred by the compiler; the parameter types may be explicitly specified or they may be inferred from the assignment context.

The type of a formal parameter can be omitted, in which case the compiler will infer a type from the target type of the lambda conversion. Let us see couple examples where the types are inferred by the compiler.

	enum Decision {
	    APPROVE, DECLINE, APPROVE_REFER
	}

	abstract class DecisionService {
	    abstract Decision getRiskDecision(Applicant applicant);
	}

	class Applicant {
		private int score;
		public Applicant(int score) {
			this.score = score;
		}
		public int getScore() {
			return score;
		}
	}

	public void test() {
		DecisionService cs = #{ a ->
								if (a.getScore() > 700) {
									return Decision.APPROVE;
								} else if (a.getScore() > 600 && a.getScore() < 650) {
									return Decision.APPROVE_REFER;
								} else {
									return Decision.DECLINE;
								}
							};
		Decision decision = cs.getRiskDecision(new Applicant(800));
		System.out.println(decision.toString());
	}

In line #20 above, the type of the formal parameter Applicant is inferred by the compiler.

	class Payment {
		private int amount;
		Payment(int amount) {
			this.amount = amount;
		}
		public int getAmount() {
			return amount;
		}
	}
	interface PaymentProcessor {
		void process(Payment pmt);
	}
	{
		invokeProcessor(#{pmt -> log("Processed # " + pmt.getAmount() + " at " + new Date())});
	}
	void invokeProcessor(PaymentProcessor processor) {
		processor.process(new Payment(42));
	}

In line #14, the type of the formal parameter Payment is inferred by the compiler.

Extension Methods

One of the significant benefits of Lambdas is that it enables the development of more powerful libraries with less code and more efficiency. To enhance the core libraries to take advantage of these powerful language features without compromising backward compatibility, the concept of public defender methods was introduced. This proposal suggests adding virtual extension methods to existing interfaces allowing the use of new language features to enhance the capabilities of core libraries.

While, extension methods by itself is more useful and when combined with Lambdas, they can be powerful. The traditional way of sorting a collection.

        Collections.sort(people, new Comparator<Person>() {
            public int compare(Person x, Person y) {
                return x.getLastName().compareTo(y.getLastName());
            }
        });	        

With Lambdas, this can be expressed more concisely (this works with the prototype).

Collections.sort(people, #{ x, y -> x.getLastName().compareTo(y.getLastName()) });

And this still leaves room for improvement where virtual extension methods come to rescue. When core libraries are enhanced to take advantage of Lambda expressions, this can be made less verbose.

people.sortBy(#Person.getLastName);

Virtual extension methods are declared using the ‘extension’ keyword.

public interface List<T> extends Collection<T> {
	// .... The existing List methods 
  	extension void sort() default Collections.sort;
}

When Collections library is enhanced to support extensions methods, we should be able to use many of the Collections APIs directly in a collection:

List.sort();
//instead of
Collections.sort(List);

Some of these minor improvements are most sought after and makes Java less verbose and one less class to deal with.

Conclusion

I haven’t touched upon other fundamental concepts such as Exception transparency, Method references and Lexical Scoping. I will be covering them once I do some hands-on with these concepts. The prototype is still evolving around these areas and has made some good progress in catching up with this new draft. As we know, Lambdas are scheduled to go in Java 8 (in late 2012), almost six years after Closures were originally proposed in 2006. I believe there are plans to make binary builds available for all platforms, so the hassle of building from the source would no longer be required.

[Photo credit: http://www.lumaxart.com/]

Update (10/25/2010) : Omitted the use of optional trailing semicolon and return keyword in single line Lambda expressions.

Update (6/11/2011) : The definition of SAM types have changed since this post was originally written. Here is the latest definition.

SAM types:
1. An interface that has a single abstract method
2. Having more than one distinct methods, but only one is “real”, the others are overridden public methods in Object – example:

Comparator<T>

3. Having more than one methods due to inheritance, but they have the same signature
4. Having more than one methods due to inheritance, but one of them has a sub-signature of all other methods

    a) parameter types compatible
    b) return type substitutable
    c) thrown type not conflicting with the thrown clause of any other method
    d) mixed up

5. Type-dependent SAM types

non-SAM types:
6. An interface that has a single abstract method, which is also public method in Object
7. Having more than one methods due to inheritance, and none of them has a sub-signature of all other methods

With these new rules, some of the examples won’t compile. Abstract classes with single abstract method are no longer considered valid SAM types. Switching to an interface should fix these examples.

Possibly Related Posts:


Try-with-resources (originally known as Automatic Resource Management) is one of the Project Coin proposals that made its way into recent JDK 7 builds. Traditionally, developers had to manually terminate any resources (Files, Database connections, etc) they use in their applications and sometimes it was painful to keep track of those things and failing to do so may have serious problems such as resource leaks which could potentially lead to application failures that are hard to debug and triage. The burden of managing resources is no more a developer’s headache as this will be natively supported in Java 7.

C# has “using” blocks and C++ destructors served a similar purpose. This is a more sought after language feature for years and Joshua Bloch brings this to real for Java developers with some syntax sugaring. While this construct looks alien to Java, I believe this is something we have to accept and move forward as this solves common programming errors. IDEs can fill this space to support intelligent code completion for ARM constructs and make it easy for developer adoption. The other disadvantage outlined in the proposal is increased coupling between the language specification and libraries. To support this feature, a class must implement a designated interface AutoCloseable to make it eligible for automatic resource management.

Let us look at the example used in the ARM proposal, copying a file involving two resources.

    public void copy(String src, String dest) throws IOException {
        InputStream in = new FileInputStream(src);
        try {
            OutputStream out = new FileOutputStream(dest);
            try {
                byte[] buf = new byte[8192];
                int n;
                while ((n = in.read(buf)) >= 0)
                    out.write(buf, 0, n);
            } finally {
                out.close();
            }
        } finally {
            in.close();
        }
    }

With the new try-with-resources construct, we should be able to rewrite the above code with much simplicity:

    public void copy(String src, String dest) throws IOException {
        try(InputStream in = new FileInputStream(src);
            OutputStream out = new FileOutputStream(dest)){
            byte[] buf = new byte[8192];
            int n;
            while ((n = in.read(buf)) >= 0)
                out.write(buf, 0, n);
        }
    }

The bloated code we use these days will become more crisp with fewer lines of code, while continuing to maintain readability.

Java APIs that involve dealing with resources are mostly retrofitted to support this new AutoCloseable interface. This feature brings heap of benefits to the JDBC world where this may prove very useful when managing database connections and its subsidiaries.

Here is the traditional way of programming in JDBC where the user has to manage JDBC resources such as ResultSet, Statement and Connection.

        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            conn = DriverManager.getConnection("jdbc:h2:mem:test", "sa", "");
            stmt = conn.createStatement();
            rs = stmt.executeQuery("SELECT * FROM INFORMATION_SCHEMA.USERS");
            while (rs.next()) {
                System.out.println(rs.getString(1));
            }
        } catch (SQLException e) {
            // handle exception
        } finally {
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                }
                rs = null;
            }
            if (stmt != null) {
                try {
                    stmt.close();
                } catch (SQLException e) {
                }
                stmt = null;
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                }
                conn = null;
            }

        }

You guessed it right, there is so much boilerplate code that is involved here. Here is the same code with our try-with-resources construct.

        try(Connection conn = DriverManager.getConnection("jdbc:h2:mem:test", "sa", "");
            Statement stmt = conn.createStatement();
            ResultSet rs = stmt.executeQuery("SELECT * FROM INFORMATION_SCHEMA.USERS")) {// no trailing semicolon in the last line of the block containing automatic resource definition
            while (rs.next()) {
                System.out.println(rs.getString(1));
            }
        } catch (SQLException e) {
            // handle exception
        }

Wow, it is compact and powerful. JDBC support for the new try-with-resources construct will be part of JDBC 4.1 specification and the implementation is available in the recent JDK 7 build 112.

In these try-with-resources examples, an exception thrown during the lifetime of a try-with-resources statement receives priority over an exception thrown by an automatically generated close invocation. The proposal addresses automatic retention of those suppressed exceptions which are associated with the primary exception thrown during the try-with-resources statement.

The following methods are added to java.lang.Throwable to support extraction of these suppressed exceptions.

    public synchronized void addSuppressedException(Throwable exception);

    public synchronized Throwable[] getSuppressedExceptions();

You may want to go through the recent JavaOne presentation which details Project Coin features that are included in Java 7, slated for release in mid 2011.

Do you think Project Coin will become a crown jewel of Java 7, since Lambda expressions and Project Jigsaw are no longer the main contenders? In the coming days, I will be exploring many other language features that are included in Java 7 and help you decide the crown jewel of Java 7.

Keep watching this space for more Java 7 delicacies 🙂

Possibly Related Posts:


Tony Printezis provided some insight into G1 in JavaOne last year. Now, we can see G1 in action with the latest JDK 6 builds. HotSpot JVM features this new collection mechanism in the recent Java SE update 14 early access builds (since b02). It is not enabled by default as this is still an experimental beta feature. But it is quite easy to enable this option for your application.

To enable it, use the JVM option:

-XX:+UnlockExperimentalVMOptions -XX:+UseG1GC

The available collectors in JDK 6 are:

1. Serial (-XX:+UseSerialGC)
2. Parallel (-XX:+UseParallelGC)
3. Concurrent (-XX:+UseConcMarkSweepGC)

Sun’s research paper explains the algorithm behind this collector. The G1 collector is meant to be an alternate for the concurrent collector for the HotSpot 14.

Java SE 6 Update 14 FCS is planned for Q2 2009. The latest available build is b03.

I did play with this new feature from b02 and my initial tests showed that it does not perform better yet than the concurrent collector. I am planning to run some more tests with b03 and will keep updated on my findings.

Possibly Related Posts: