Building Your First OpenJDK

5 min read Original article ↗

It’s common to think of runtimes and VMs as black boxes that execute app code and stay behind the scenes. But sometimes understanding a program’s performance characteristics requires leaving handwavy statements like “the JIT will probably optimize that out” behind and doing the hard work: digging deeper. One of the most powerful steps a programmer can take toward understanding a VM’s operation is to crack open the box and dig inside. To that end, we’re going to build our own OpenJDK. Once you’ve rooted around in the source of your VM to see how things fit together and built it yourself, you’ve gained an uncommon understanding of what happens under the hood. But more importantly, once you’ve successfully built a program (or a VM), you can modify it and make it better. So, let’s get started!

This walk-through is based on the OpenJDK build README located here. I’ve added information specific to a particular OS and build environment, included the list of packages required to successfully build the VM, and (hopefully) included enough details to help you make your first build a successful one – rather than spending hours hunting each of these down.

Setting up a Build Environment

To build our JDK, we’ll begin with Ubuntu 12.04.2 as a base. Start by grabbing a fresh ISO of Ubuntu 12.04 LTS (64-bit) Desktop from here. Set up the virtual machine in your hypervisor of choice - VMWare and VirtualBox are popular choices. Be sure to give it at least 2GB of RAM and two cores to work with (the more the merrier). Once you’ve got a fresh dev environment up and running, we’ll need to install a few packages and tools to lay the groundwork for our build environment.

Let’s start with:

sudo apt-get install \
     build-essential  \
     gawk             \
     libcups2-dev     \
     libfreetype6-dev \
     lib32asound2-dev \
     libx11-dev       \
     libxext-dev      \
     libxp6           \
     libxrender-dev   \
     libxt-dev        \
     libxtst-dev      \
     mercurial        \
     vim

Next, make a ~/src directory to work from to keep things clean. We’ll do our work in here.

Fetching a Bootstrap JDK

Like many compilers and VMs, new versions of OpenJDK are built by bootstrapping using a previously-released “boot JDK” to build a newer version. The minimum boot JDK for Java 7 is Java 6u18. However, the current version of the SSL cert on java.net is not supported by the older 6u18 JDK (released in 2009), so we’ll use the newest Java 6 release available. Your best bet is to start with 6u38 or higher. Download the “Linux x64 self-extracting JDK file” (jdk-6u38-ea-bin-b04-linux-amd64-31_oct_2012.bin; MD5 555b956fdfea479d404e44e4a27639f1) from here and drop it in your ~/src directory. When you’ve got it, chmod +x it and run the self-extracting binary and chmod +x it.

chmod +x jdk-6u38-ea-bin-b04-linux-amd64-31_oct_2012.bin
./jdk-6u38-ea-bin-b04-linux-amd64-31_oct_2012.bin

Setting up Source Control

The OpenJDK project uses Mercurial (“hg”) for source control. The “forest” plugin makes it easier to manage collections of repositories. In your ~/src directory, fetch it with:

hg clone https://bitbucket.org/pmezard/hgforest-crew/overview \
~/src/hg-forest

Then, enable the extension by creating a file in your home directory called ~/.hgrc with the following contents:

[extensions]
forest = ~/src/hg-forest/forest.py

Getting Started with Ant

We also need to install Apache Ant, which is used to orchestrate the JDK build process. In your ~/src directory,

wget http://apache.mirrors.tds.net/ant/binaries/apache-ant-1.9.1-bin.tar.gz
tar -xvzf apache-ant-1.9.1-bin.tar.gz

Environment Variables

Let’s set up a few environment variables. Add the following to your ~/.bashrc (if you’re using an interactive shell), ~/.bash_profile (if you’re working via SSH), or otherwise make them available to your environment, and open a fresh shell:

export PATH=~/src/jdk1.6.0_38/bin:~/src/apache-ant-1.9.1/bin:$PATH
export ALT_BOOTDIR=~/src/jdk1.6.0_38
export LANG=C

Cloning the Source with Mercurial + Forest

Now, we’re ready to clone the OpenJDK source. In your ~/src directory, fetch it by typing (yes, fclone):

hg fclone http://hg.openjdk.java.net/jdk7/jdk7 openjdk7

Patches to Build on Ubuntu 12.04 LTS

As of July 5, 2013, there are patches that need to be applied to build the hg tip of OpenJDK7 on Ubuntu 12.04.

To apply the first patch (for bug #7103224):

1. cd ~/src/openjdk7/hotspot
2. wget http://hg.openjdk.java.net/hsx/hotspot-comp/hotspot/raw-rev/a6eef545f1a2
3. hg import a6eef545f1a2

And the second (for bug #7110396): Patch: http://mail.openjdk.java.net/pipermail/build-dev/2012-January/005382.html

This can be saved to a file and applied with hg import, or manually applied by making the one-line change specified in the jdk/ subdirectory.

Building Your First JVM + JDK

Finally, it’s time to build! In ~/src/openjdk7, run:

make ALLOW_DOWNLOADS=true \
     DISABLE_HOTSPOT_OS_VERSION_CHECK=ok

We pass ALLOW_DOWNLOADS to direct ant to fetch sources for JDK components that you might not have already downloaded. The DISABLE_HOTSPOT_OS_VERSION_CHECK flag is necessary for building the VM on 3.x-series kernels, as the makefile has not yet been updated to include 3.x in the list of supported build environments.

The first build will likely take about 20 minutes, so making a cup of coffee might not be a bad idea. If the build succeeds, you should be able to launch your newly-built JVM and JDK. Let’s give it a shot!

cscotta@ubuntu:~/src/openjdk7$ build/linux-amd64/bin/java -version
openjdk version "1.7.0-internal"
OpenJDK Runtime Environment (build 1.7.0-internal-cscotta_2013_07_05_17_51-b00)
OpenJDK 64-Bit Server VM (build 21.0-b17, mixed mode)

If the VM initalizes as expected, printing its version and build information, you’re good to go!

(Note that if you do not update your path to include ~/src/openjdk7/build/linux-amd64/bin, default invocations of commands like java, javac, and so on will continue to use the 6u38 build of Java that we downloaded earlier.

Oh, and a tip! Once you’ve built the JDK once, you can request that successive compilations re-use your prebuilt sources. To rebuild against our previously-built artifacts, run make from your ~/src/openjdk7 directory with:

make ALLOW_DOWNLOADS=true      \
     DISABLE_HOTSPOT_OS_VERSION_CHECK=ok \
     ALT_JDK_IMPORT_PATH=build/linux-amd64/j2sdk-image

Coming up Next

In the next post, we’ll look at what it takes to make changes to our JDK/JVM, add a native method that exposes some internal VM state, and learn how to call it. Stay tuned!


Questions or comments?

I hang out on Twitter as @cscotta and on Freenode as cscotta. Feel free to say hello!