libjawt.so, java-gcjHEAD-compat, Big Merge

Here’s a screenshot of a JOGL demo running on Sun and libgcj:

JOGL Demo on Sun and libgcj

As you can see, it’s hard to tell which is which!

Big Merge

The screenshot represents several efforts coming together. First, the demo is running on natively-compiled GNU Classpath HEAD. Tom Tromey recently finished the Big Merge, making Classpath a sub-directory of gcc/libjava. To develop this demo, I replaced gcc/libjava/classpath with a checkout of Classpath HEAD and rebuilt libgcj. After patching a few places where divergences crept in I have a GCJ HEAD + Classpath HEAD development environment setup. Developing in this way is much more pleasant than the previous merge-every-patch approach; now I use the same source checkout for libgcj and JamVM+Classpath.

java-gcjHEAD-compat

The screenshot shows me running the java command in the exact same way in both windows, thanks to java-gcjHEAD-compat. It is an RPM spec file that allows you to create a first-class JPackage-style JVM alternative that points to a GCJ installation in a non-standard prefix. For example, I’ve installed GCJ HEAD in /home/fitzsim/install. java-gcjHEAD-compat points /usr/bin/java (through alternatives) to /home/fitzsim/install/bin/gij.

This is very convenient for developing libgcj as a JPackage JVM replacement since all JPackages assume the JVM is installed in /usr/lib/jvm. It’s also useful for building RPMs against libgcj HEAD, which I’ve done with JOGL in the screenshot. Now, JOGL is a heavy user of the AWT Native Interface which is implemented by a small library, libjawt.so. That brings me to my next topic.

libjawt.so Binary Compatibility

It has proved quite challenging to create a drop-in replacement for Sun’s libjawt.so. The jawt.h and jawt_md.h headers that Sun includes in the AWT Native Interface document are marked confidential and proprietary so I didn’t want to refer to them when creating an implementation for GNU Classpath. My initial libjawt.so attempt was not binary-compatible and so created problems for packages like JOGL that need to run on either libgcj or a proprietary JVM.

Using gdb and ptype I was able to determine the layout of JAWT types, so now libgcj’s libgcjawt.so is binary-compatible, except that its SONAME is versioned by libtool. But the SONAME of Sun’s libjawt.so is unversioned, simply “libjawt.so”, so even naming our library the same would not produce a binary-compatible result (e.g. “libjawt.so.6”) — and besides, doing so would cause confusion since libgcj’s “libjawt” is always present in the default library path, whereas Sun’s libjawt is not. So, what to do?

The last step in drop-in replaceability turned out to be a clever trick that Jakub Jelinek suggested:

libjawt.so:
	echo | $(GCJ_BIN_DIR)/gcc$(gcc_suffix) -shared -O2 -fpic -o libjawt.so -Wl,-soname,libjawt.so -xc - -lgcjawt

That’s a line from java-gcj-compat’s Makefile.am. It creates an empty library with the proper SONAME that links to the versioned libgcjawt.so. That’s it! java-gcj-compat’s libjawt.so gets installed in $JAVA_HOME/jre/lib/i386 just like Sun’s and apps needing libjawt.so to build or run don’t know the difference! I was relieved that this step was so simple — I was expecting linker script madness.

The proof that this all works is in the screenshot; I built Anthony Green‘s JOGL RPMs using java-gcjHEAD-compat and its libjawt.so and I’m running the JOGL demo on both Sun and java-gcjHEAD-compat. lsof shows the correct libjawt.so being loaded in each case:

$ /usr/sbin/lsof | grep libjawt.so
java      32435 fitzsim  mem       REG        3,2     2680     470785 /usr/lib/jvm/java-1.4.2-gcjHEAD-1.4.2.0/jre/lib/i386/libjawt.so
java      32460 fitzsim  mem       REG        3,2     3824     812009 /usr/java/jdk1.5.0_01/jre/lib/i386/libjawt.so

Now I want to see JOGL submitted to Fedora Extras and all this binary-compatibility work land in Fedora Core 5!

GtkImage peer rewrite

Sven de Marothy completely rewrote the image-handling sections of the GTK peers. This was one of the most convoluted areas in the peers and one of the buggiest. Now it is very clear and well-organized. Check out this screenshot:

The top is JDK 1.4, centre is Classpath 0.14 and bottom is Classpath HEAD with Sven’s patch. This work is awesome because it means we’ll have a solid foundation when we make the transition to using BufferedImages exclusively. Thanks Sven!

java-gcj-compat status

I submitted my ecj option parsing patch to Eclipse.

The patch went into Rawhide’s eclipse-ecj last night, which meant I was able to remove the last option munging stuff from java-gcj-compat. Behold:


$ ls -l /usr/lib/jvm/java-gcj/bin
jar -> /usr/bin/fastjar
java -> /usr/bin/gij
javac -> /usr/bin/ecj
javadoc -> /usr/bin/gjdoc
javah -> /usr/bin/gjnih
rmic -> /usr/bin/grmic
rmiregistry -> /usr/bin/grmiregistry

No wrapper scripts, just direct symlinks. All these tools are now command-line compatible with their proprietary equivalents.

java-gcj-compat’s remaining holes are representative of the entire free stack’s J2SE deficiencies. Specifically:

  1. dependencies on external crypto providers
  2. no CORBA tools
  3. no Java plugin

These are the areas that we need to focus on this year. 1 should be pretty easy; just a matter of merging GNU Crypto, Jessie and Bouncy Castle into GNU Classpath. 2 will be harder. Ideally we could get JacORB dual-licensed LGPL/GPL+exception, reimplement all the non-free OMG headers it uses and merge it into GNU Classpath. Quite a bit of effort. 3 will be harder still; we’ll need to finish libgcj’s security implementation (with test suites and everything) and fix many bugs in our AWT and Swing implementations.

AWT buffer strategies

I finished GNU Classpath’s BufferStrategy framework tonight:

AWT BufferStrategy test.

Currently there is only one unaccelerated backend that doesn’t actually do anything, but the framework for adding new backends is in place as well as all the necessary documentation.

This patch adds the missing methods that Caolan mentioned in his blog. This is the last GCJ AWT vs. OO.org problem I’m aware of, so I think we’re in good shape for Fedora Core 4.