Musings on software development…

Building JDK8 with Lambda Support

Following my recent trip to Devoxx 2011 and from attending Mark Reinhold‘s and Brian Goetz‘s talks on JDK8 and Lambda, my interest was piqued to try and get this all working for myself. I thought that as I’m doing it and as I might not be the only one who wishes to try this out, I should blog my experience in getting to the point of writing a lambda expression (a closure) and getting it to compile and run using JDK8.

References:

Here are some references to start to learn about JDK8 and Lambda:

  • An excellent PDF slide presentation from Brian Goetz from Devoxx 2011 can be found here.
  • The Lambda specification (JSR335) can be found here.
  • The JDK8 specification (JSR337) can be found here.
  • And of course, the OpenJDK project website can be found here.

Any further references will be linked in this article text.

Stop! Read Me First!

As pointed out on the mailing-list, there are already bundles available to you if you only want to try out JDK8 with Lambdas. This posting is only for people who wish to keep at the bleeding edge and compile from source, quicker than the bundles are released for general consumption. Using prebaked bundles is a far easier route and a quicker entry into learning what this exciting new feature brings to Java :-) I would encouage you to try out the bundles and save yourself time in doing all the stuff described below. Saying that, if you do want to build from source, then please do read on…

Some prerequisites:

This is my starting point. Some basic requirements have to be met before you can build JDK8 with Lambdas:

  • I am running Debian Testing within a VM using Parallels to build the JDK:
    • configured with 2 virtual CPUs and 2GB of RAM
  • JDK7 is required to build JDK8:
    • apt-get install openjdk-7-jdk
    • apt-get build-dep openjdk-7-jdk
  • You need mercurial installed:
    • apt-get install mercurial

Please note: You don’t need Debian to compile JDK8 with Lambda, this is just my way of doing it. You can compile in Solaris, MacOS X, RedHat, Centos and even Windows…please refer to the build instructions on supported build platforms and architectures.

Obtaining the JDK8 with Lambda source code:

Currently, to build JDK8 with Lambda, one needs to clone a separate repository away from the main JDK8 repository. This special Lambda repo contains the code changes to the JVM and other bits to make lambda expressions work. It actually pulls down all the other base JDK8 source files but has special source files for switching on Lambda. Once cloned, the build instructions are the same as if one was compiling the base JDK8 packages. Therefore, the first thing you need to do is clone this Lambda-aware repo:

hg clone http://hg.openjdk.java.net/lambda/lambda

When cloning has finished, pop into the lambda directory and run:

sh ./get_source.sh

This will clone the other dependent repos (such as hotspot, corba, jdk, langtools and so on) into the lambda directory. This process shouldn’t take too long – a few seconds or so.

From this point onwards, the build instructions on the OpenJDK for building JDK8 apply. The instructions do talk about JDK7, but the same rules apply for JDK8 (I guess they just have to be updated). There are a few gotcha’s which I have done my best to document below:

Obtaining JAXWS and JAXP source code:

This is quite easy. Just look in the jaxp/jaxp.properties file for the name of the JAXP version to download, I then used wget to retrieve the zip archives, i.e.,

  • wget http://download.java.net/jaxp/1.4.5/jaxp145_01.zip
  • wget http://download.java.net/jaxp/1.4.5/jaxp-1_4_5-unittests.zip

You want to put those zip files into a directory outside of the lambda cloned directory. I have mine in a directory called “drops.” Do the same for JAXWS. Just look in the jaxws/jaxws.properties file for the name of the JAXWS version to download. Put the zip archive files into the “drops” directory along with the JAXP files. For those interested, here is what my drops directory looks like:

If you are curious about my overall directory structure, I’ve attached a screenshot below. Please note that I build openjdk8 in addition to the lambda project, that is why I have a do_openjdk script file and an openjdk8 folder (and why in my drops folder I have jdk8 versions of JAF and JAXWS):

Cloning (and building) the defender-prototype project:

For the moment, it is necessary whilst building JDK8 with Lambda, to include another very important project in the build process. This project uses reweaving to enable defender methods that are a cornerstone of using Lambdas with Java. Eventually the JVM will be clever enough to understand defender methods, but for now we need a special javaagent called jsr335-agent when building JDK8 with Lambda. This agent is built from the defender-prototype project.

The first step is to clone the defender-prototype repo into the same level as the lambda project (see below for a screenshot):

hg clone http://hg.openjdk.java.net/lambda/defender-prototype

The second step is to download the required library dependencies. You need to create a folder called “lib” in the defender-prototype directory and drop in the following two jars:

  • testng-6.2.jar
  • asm-4.0_RC1.jar

You can find these jars from the testng website and the asm website.

Finally, you can build the jsr335-agent.jar

  • ant

The output of this will be a file called jsr335-agent.jar in the distrib directory.

Here is a screenshot of my directory layout now. Please note the defender-prototype directory at the same level as the lambda directory:


Pretty isn’t it? :-)

Building JDK8 and baking in Lambda support (FTW!):

This part is the easy part. Nothing much to do here. I wrote a little build script (called do_lambda.sh) to automate the build process. You can clearly see where I put this script from the screenshot above:

#!/bin/bash
unset JAVA_HOME
export LANG=C
# JDK7 is required to build JDK8 with Lambda support
export ALT_BOOTDIR=/usr/lib/jvm/java-1.7.0-openjdk-amd64
# The location of JAXP and JAXWS source zip files
export ALT_DROPS_DIR=/home/david/development/openjdk8/drops
cd lambda
sh ./make/scripts/hgforest.sh pull -u
. jdk/make/jdk_generic_profile.sh
make sanity && make all

Whilst the build is happening, you can go make a coffee or a nice cup of tea. It will take a while.

Writing your first Closure (or Lambda!):

Now comes the time of great rejoicing and excitement. Now, for the first time, you can write closures in Java and functions are treated as first-class citizens! If I am honest here, I’m not that familiar with functional/closure type programming but I’m quite eager to learn. I took a few minutes to knock up an example, so below I give you a little Hello World!

public class HelloWorldClosure {

    interface C {
        String c();
    }

    public static void main(final String[] args) {

        final C c = () -> "Hello World";
        System.out.println(c.c());

    }
}

And of course, the result:

Not bad for an afternoon of hacking around. :-)

I’m very excited in this new language feature coming in JDK8. It is a much-needed addition to Java now that we live in the age of multi-multi-core computers :-) I wish to thank all those on the Expert Group for their continued development of Lambda’s for Java – even for an average-joe type programmer like myself, I’m sure I will use them extensively :-)

About these ads

Written by dharrigan

November 20, 2011 at 6:54 pm

Posted in development, java

One Response

Subscribe to comments with RSS.

  1. Just a reminder that you need to rename ‘asm-all-4.0_RC1.jar’ to ‘asm-all-4.0.jar’

    Richard Warburton

    November 24, 2011 at 11:53 pm


Comments are closed.