Update (12/04/2007) : The tutorial has now been upgraded to the include the latest releases of the javac compiler and jtreg harness. I wish to express my gratitude to Lubo Litchev from Sun Microsystems for his insights and ideas for improving this tutorial.
Note : This entry will deal only with downloading and setting up a Windows-based environment for compiling the compiler, running it and running the regression tests, using a bare-bones shell. If you have already done that, you can go directly to the next article. Also, I usually like to write without assuming what the reader may or may not know. Sorry if I sound pedantic at times, I just want everyone to be ableo to follow.
Of course, the first thing you need before you can hack the OpenJDK compiler are the sources themselves. You can get them here. Also, if you are interested in maintaining java compatibility, you should download the jtreg test harness in order to perform the regression tests (the tests themselves are part of the compiler distribution).
Note : In the chapters that follow, we have used specifically the following releases
Once you have downloaded both distributions, you should unzip them somewhere. For specificity, I will assume from here onwards that the compiler has been unzipped in a path called "F:\javac" and that the jtreg test harness has been unzipped in "F:\". This should end you with a path structure like this:
Seems easy, doesn't it? Hah!. In Windows, the files you get in the bin directories require some wierd, unix-like shells pre-installed in order to be run properly. Not that you can't run them without the shells, but it is much more easy if you go down the "recommended" way. MKS and Cygwin are suggested in the jtreg site, but since MKS is commercial software, guess which one I picked.
Ok, on the cygwin front page, download and run the "setup.exe" program that will install that shell on Windows.
Beware that according to the cygwin FAQ, some antivirus software (Network Associates, Norton) cause setup to hang, so you should disable them prior to running it .
On the first screen, select "Install from Internet" unless you have previously downloaded the required packages by yourself.

On the next screen, select a random directory for placing the whole thing

On the following screen, select a directory for the downloaded packages.

On the Connection Type screen, adjust your connection settings appropriately

Choose your mirror. Try to choose one that is both big and near geographically.

Finally, the package list you wish to install. The default collection is ok for our purposes, so you don't need to expand anything or select anything else. Just click on the "Next" button and the setup program will start downloading and installing packages. The process may take some time.

After you have finished downloading stuff, you'll hava a cygwin icon on the desktop:
Click on it and you'll see the typical Linux prompt:
Alexander@host ~
$
By default, cygwin mounts all drives at /cygdrive/<drive-letter>, so for example drive F: is /cygdrive/f. You can see all mounted drives by using the mount command, which will get you something like:
$ mount
C:\cygwin\bin on /usr/bin type system (binmode)
C:\cygwin\lib on /usr/lib type system (binmode)
C:\cygwin on / type system (binmode)
c: on /cygdrive/c type system (binmode,noumount)
e: on /cygdrive/e type system (binmode,noumount)
f: on /cygdrive/f type system (binmode,noumount)
g: on /cygdrive/g type system (binmode,noumount)
i: on /cygdrive/i type system (binmode,noumount)
u: on /cygdrive/u type system (binmode,noumount)
x: on /cygdrive/x type system (binmode,noumount)
z: on /cygdrive/z type system (binmode,noumount)
The next step is to compile the source distribution. Grab a copy of ant from the official site and uncompress it somwehere. Add the bin subdirectory of the uncompressed location to your path, and define and environment variable called ANT_HOME pointing to the place you uncompressed ant. Once you have done that, you're ready to go. Drop to the windows command prompt, go to the directory where you uncompressed the compiler and simply run
ant -buildfile build.xml
You should see something like this:
F:\javac\compiler>ant -buildfile build.xml
Buildfile: build.xml
prep:
[mkdir] Created dir: F:\javac\compiler\build\bootclasses
[mkdir] Created dir: F:\javac\compiler\build\classes
[mkdir] Created dir: F:\javac\compiler\dist\bin
[mkdir] Created dir: F:\javac\compiler\dist\lib
check-javac.isuptodate:
build-lib.javac.jar:
[mkdir] Created dir: F:\javac\compiler\build\gensrc\com\sun\tools\javac
[copy] Copying 1 file to F:\javac\compiler\build\gensrc\com\sun\tools\javac
\resources
[javac] Compiling 251 source files to F:\javac\compiler\build\bootclasses
[javac] F:\javac\compiler\src\share\classes\com\sun\tools\javac\processing\J
avacProcessingEnvironment.java:71: warning: sun.misc.Service is Sun proprietary
API and may be removed in a future release
[javac] import sun.misc.Service;
[javac] ^
[javac] F:\javac\compiler\src\share\classes\com\sun\tools\javac\processing\J
avacProcessingEnvironment.java:72: warning: sun.misc.ServiceConfigurationError i
s Sun proprietary API and may be removed in a future release
check-javac.isuptodate:
....
[java] F:\javac\compiler\src\share\classes\com\sun\tools\javac\model\Annota
tionProxyMaker.java:252: warning: sun.reflect.annotation.ExceptionProxy is Sun p
roprietary API and may be removed in a future release
[java] value = new ExceptionProxy() {
[java] ^
[java] 14 warnings
[copy] Copying 7 files to F:\javac\compiler\build\classes
[jar] Building jar: F:\javac\compiler\dist\lib\javac.jar
build-bin.javac:
[copy] Copying 1 file to F:\javac\compiler\dist\bin
build:
BUILD SUCCESSFUL
Total time: 1 minute 10 seconds
F:\javac\compiler>
You'll be getting lots of warnings, but that's ok. There should be no errors, though.
To run the compiler, go to the cygwin shell, switch to the "compiler/dist/bin" directory and run
./javac -version
You should get the following:
Alexander@planetalia /cygdrive/f/javac/compiler/dist/bin $ ./javac -version javac 1.7.0-opensource
If instead you get something like:
Alexander@planetalia / $ cd /cygdrive/f/javac/compiler/dist/bin
Alexander@planetalia /cygdrive/f/javac/compiler/dist/bin $ ./javac -version
Exception in thread "main" java.lang.UnsupportedClassVersionError: Bad version n umber in .class file at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:620) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:12 4) at java.net.URLClassLoader.defineClass(URLClassLoader.java:260) at java.net.URLClassLoader.access$100(URLClassLoader.java:56) at java.net.URLClassLoader$1.run(URLClassLoader.java:195) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:188) at java.lang.ClassLoader.loadClass(ClassLoader.java:306) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:268) at java.lang.ClassLoader.loadClass(ClassLoader.java:251) at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319) Alexander@planetalia /cygdrive/f/javac/compiler/dist/bin
this would probably be caused by a jre mismatch.
When ant compiles the compiler for the first time, it uses the installed JRE, but after that step has finished, Ant recompiles the compiler with itself, meaning that the class file format that is used corresponds to the very last version. This means that running the compiler requires having the latest (beta or RC) JRE, so be sure to have it installed.
Now you shouldn't have any trouble running the compiler. We'll try the typical "hello world" application, and we'll assume that you save it in the compiler/dist/bin folder
public class Test { public static void main(String[] args) { System.out.println("Hello world"); } }
Now, simply go to the location of this file and compile it using javac
Alexander@planetalia / $ cd /cygdrive/f/javac/compiler/dist/bin Alexander@planetalia /cygdrive/f/javac/compiler/dist/bin $ javac Test.java Alexander@planetalia /cygdrive/f/javac/compiler/dist/bin $ java -cp . Test Hello world Alexander@planetalia /cygdrive/f/javac/compiler/dist/bin $
Now on to jtreg/javatest. I think the whole jtreg/javatest shell script is a mess when combined with Cygwin, because:
So the end result is that basically you have to write your own script for running the regression tests. I used the following one:
#!/bin/sh JT_HOME="f:/jtreg/" CYGWIN_JAVA_HOME="/cygdrive/c/Archivos de Programa/Java/jdk1.5.0_05" JAVAC_HOME="f:/javac/compiler" "$CYGWIN_JAVA_HOME/bin/java" \ -jar /lib/jtreg.jar -verbose \ -Xbootclasspath/p:$JAVAC_HOME/dist/lib/javac.jar \ -noshell $JAVAC_HOME/test/tools/javac
where you should alter the first three variables to match your locations.
Make sure you save this file in UNIX format! (i.e: using LF as line terminator and not CR/LF). Place this script in jtreg/win32/bin and run it. You should see something like this:
Alexander@planetalia /cygdrive/f/jtreg/win32/bin $ jtreg-win Directory "JTreport" not found: creating Directory "JTwork\scratch" not found: creating runner starting test: tools/javac/4980495/static/Test.java runner finished test: tools/javac/4980495/static/Test.java Passed. Compilation failed as expected runner starting test: tools/javac/4980495/std/Test.java runner finished test: tools/javac/4980495/std/Test.java Passed. Compilation failed as expected runner starting test: tools/javac/5045412/Bar.java runner finished test: tools/javac/5045412/Bar.java Passed. Compilation failed as expected runner starting test: tools/javac/5045412/Bar.java#id1 runner finished test: tools/javac/5045412/Bar.java#id1 Passed. Compilation failed as expected runner starting test: tools/javac/5045412/Foo.java
After some time (5-10 min on a reasonable machine), the regression tests will stop and you'll get a message like:
runner finished test: tools/javac/VoidArray.java Passed. Compilation failed as expected Test results: passed: 1.089; failed: 33; error: 5 Report written to JTreport\report.html Results written to F:\jtreg\win32\bin\JTwork Error: Some tests failed or other problems occurred.
Alexander@planetalia /cygdrive/f/jtreg/win32/bin $