Porting Java 6 to FreeBSD Sparc

03 Feb 2008, 22:16 PST

Over the weekend I implemented an initial port of Java 6 to FreeBSD/Sparc64, primarily as a learning exercise -- I wanted to see how difficult it is to port Java to a platform where both the processor and operating system are already independently supported.

landonf@conpanna:bsd-sparc> uname -s -m
FreeBSD sparc64
 
landonf@conpanna:bsd-sparc> ./bin/java -server Hello
Hello, World

I believe this is the first port of the Sparc JVM to a non-Solaris system, and the work should be applicable to supporting other operating systems, such as NetBSD or Linux Sparc systems. This article will discuss the steps I took, with the hope of aiding future porters.

The JRL-licensed code can be downloaded here: patch-java6-freebsd-sparc-1.gz

By downloading these binaries or source code, you certify that you are a Licensee in good standing under the Java Research License of the Java 2 SDK, and that your access, use, and distribution of code and information you may obtain at this site is subject to the License. To ensure compliance, downloading requires "click-through" authentication:

Bootstrap Environment

Building Java requires Java, which is a catch-22 when you're bootstrapping an unsupported system. To work around this, I used an idea (and scripts) suggested by Havard Eidnes: I set up a second Linux system running Sun's Java, and then mounted my FreeBSD build directory at the exact same path on the Linux machine.

Havard's scripts ssh to the bootstrap host and run the Java commands there. The source files are read from the NFS build tree, and the output files are written back.

You can download my slightly modified version of Havard's scripts here: boot-java.tar.gz. Any bugs are surely my own. To use the scripts, set the following environmental variables:

When calling make, you must also ALT_BOOTDIR to the boot-java path (eg, $HOME/boot-java).

Getting it Running

I started by running 'make' and filling in the blanks -- the best approach is to copy liberally from existing platform implementations. In most cases, I borrowed the solaris-sparc implementation, and merged in code from the bsd-amd64 counterpart:

Nearly all the new code needed to be added to hotspot/src/os_cpu/bsd_sparc. I took an iterative approach, starting from the Solaris code, merging in BSD-specific code, and attempting to build the result. Except for the slow machine I was working with (400Mhz!), merging in the BSD code was a fairly swift process.

Sun Studio vs. GCC

Sun builds the Solaris VM using the Sun Studio toolchain, which is not fully compatible with GCC. I had trouble with gcc 3.4, and eventually settled on 4.0, which worked almost perfectly, barring three issues.

First, gcc defines 'sparc' as a standard preprocessor macro. You can guess how well that works while compiling a sparc-related code; passing the -ansi flag disables the define.

Secondly, gcc does not support passing non-const objects as a reference parameter, while Sun Studio allows it. Relying on this is non-standard, but easily fixed -- see 'Reference to a non-const object cannot be initialized with an r-value of that object'.

Lastly, I had to rewrite the Sun Studio inline assembler template (hotspot/src/os_cpu/solaris_sparc/vm/solaris_sparc.il) in standard assembler. A good discussion of the differences between Studio's inline assembler and GCC-style assembly can be found at Alfred Huang's blog. This was straight-forward -- here's an example:

.inline _Atomic_swap32, 2
.volatile
swap    [%o1],%o0
.nonvolatile
.end

Re-written as:

.global _Atomic_swap32
.align 32
_Atomic_swap32:
    swap    [%o1],%o0
    retl
    nop