Caps Lock seems to be stuck on but Corel Office for Java basically works on GNU Classpath!
Here’s a screenshot of a JOGL demo running on Sun and libgcj:
As you can see, it’s hard to tell which is which!
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.
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-126.96.36.199/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!
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!
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:
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.
I finished GNU Classpath’s BufferStrategy framework tonight:
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.
The Fedora Core 4 Eclipse Bugzilla plugin now supports HTTPS sites:
Getting this working involved quite a bit of testing and integration work. Casey fixed an x509 parsing bug, I merged GNU Classpath’s HTTPS handler into libgcj and I packaged Jessie’s SSL provider.
Next step: merge Jessie into GNU Classpath.