UbiComp:Hacking:Java:J9

From PublicWiki
Jump to: navigation, search

Introduction

Here I hope to document in a permanent way attempts and tricks to getting IBM's J9 Java VM running on an iPAQ Pocket PC with a Linux workstation as a development environment. Linux will (of course) end up being the tricky part.

These notes will mainly concern the J9 distribution packaged with Intel Placelab. Specifically the version I'm using appears to be build version 5.5.0 of J9 with SWT version 2.130.


J9 Eclipse Integration

It's a good idea to be running the same VM in our development environment and our target platform. However, we can't install the distribution of J9 included with PlaceLab as a new JRE in Eclipse, since J9 has a different directory structure than a standard VM. As a solution to this problem, there exists an Eclipse plugin that makes J9 installable as a JRE in Eclipse. The plugin is in the main eclipse CVS repository and can be browsed at the Eclipse ViewCVS page for the plugin.

Unfortunately, this plugin is not completely compatible with the J9 distributed with PlaceLab. Specifically, the existing plugin looks for a number of files in the incorrect location, all of which are referenced in the org.eclipse.jdt.internal.launching.j9.J9VMInstallType class. I've written a patch to this file that fixes the paths.

You can find the patch at UbiComp:Hacking:Java:J9:EclipseJ9JREPluginPatch

Once the patch has been applied, the plugin can be rebuilt (File > Export > Deployable plug-ins and fragments) to a zipped distribution file, which can then be unziped in the plugins/ directory of your Eclipse distribution. Once the plugin is installed, adding J9 as a new JRE is easy. Goto the JRE installation page (Window > Preference > Java > Installed JREs), add a new JRE, and select 'J9 VM' in the drop-down for 'JRE Type'. The rest is just a matter of selecting the proper path to the J9 distribution.

Adding the J9 JRE

At this point, J9 should now be installed as a VM, which means you can create new projects that use this VM. Hopefully, this will make it easier to make sure that code that runs in your IDE will also run on your target device.

J9 Ant Integration

Interested in compiling source with J9 from within an Ant build file? Typically, you specify a specific compiler in Ant using the build.compiler tag. However, it should come as no surprise that J9 is not an available option. As such, I whipped up a quick compiler adapter that you can use, which you can find at http://www.cs.washington.edu/homes/bdferris/dist/org.traditionalcake.j9.ant.jar . To use, define two properties in your ant build:

   <property name="build.compiler" value="org.traditionalcake.j9.ant.J9CompilerAdapter" />
   <property name="j9.home" value="path to J9 base here" />

Next, if running Ant from the command line, simply add the JAR to your classpath. If running Ant from within Eclipse, go the workspace setting and modify the Ant Runtime to include the specified JAR by 'Adding an External Jar' to the global entries section.

Just as a note to self, the main differences between javac and j9c is that j9c lacks both a -sourcepath option and '@' file list support (did you know for regular javac, you can list all the *.java files you wish to compile in temp file and call javac @path/to/temp to get around command line length limitations on various OSes?).

Also note that the project source is available in CVS at /homes/gws/bdferris/cvsroot with a module name of org.traditionalcake.j9.ant.

J9 SWT on Linux

While running simple programs with J9 on both the command line and within Eclipse worked pretty much immediately, things got tricker when I attempted some simple SWT. Specifically, I tried some of the examples from this article, only to start getting segfaults from within J9. Segfaults in Java? Who knew?

The problem was definitely with SWT. I had initially attempted to use the build of SWT included with Eclipse (3.1M6 with SWT 3.128), which produced lots of segfaults. The J9 distribution also contained a build of SWT in lib/prsnlwin.jar, but this build appeared to be for Windows as it kept trying to load the swt-win32-2130 native library, which doesn't appear to be included with the Linux J9 distribution (could it ever?).

What to do? Rebuild SWT using J9 and GTK. The process is largely the same as the regular SWT build process. The main change is that we will be targeting a specific version of SWT (v2.130) stripped down for the capabilities of a Pocket PC and compiled with J9. To get started, first make sure that you've properly integrated the J9 Ant Compiler Adapter mentioned previously into Eclsipse. Next, fire up Eclipse and check out the the org.eclipse.swt project from Eclipse main project CVS, making sure to get version 2130.

The SWT Jar

Next checkout the org.traditionalcake.swt.gtk.j2me project from my CVS (CVSROOT=/homes/gws/bdferris/cvsroot). Find the Ant build file (build.xml), right-click to select 'Run As > Ant Build...' Uncheck the default task of 'build.jars' and recheck these tasks in this order:

  • clean
  • property-useJ2ME
  • property-excludeAccessAndDND
  • property-excludeCustomWidgets
  • build.jars

This will build an SWT GTK package that is targeted to J2ME, has emulated accessibility and DND support and excludes custom widgets. Feel free to play with the options to get the build you want. The swt jar file will be located in the root of the org.traditionalcake.swt.gtk.j2me project.

The SWT Native Libraries

With the SWT jar built, we must now build the native JNI libraries. Begin by first copying .classpath_gtk over top of .classpath in the org.eclipse.swt project directory and reload the project. Make sure that all the classes in the resulting project build. Next, pull up your favorite terminal and goto the org.eclipse.swt/bin/library directory. Edit the make_gtk.mak file, changing the IVE_HOME path such that it points to your J9 install base. If you're like me, you've probably got a version of GTK greater than 2.4, which deprecated support for GtkCombo, on which the older SWT-2.130 depends. Edit swt.c and comment out the following line to make the old widget accessible:

   // #define GTK_DISABLE_DEPRECATED

Also, check the output of the following command:

   pkg-config --libs gthread-2.0

If the output mentions -pthread, you should go edit make_gtk_.mak and replace the occurrence of `pkg-config --libs gthread-2.0` with the output of the command, but with -pthread replaced with -lpthread. Note the addition of the -l to make it a proper linker command.

All that remains is to build the libraries:

   sh build.sh

When the process is done, you'll be left with the following two files:

   libswt-gtk-2130.so
   libswt-pi-gtk-2130.so

These are the main native libraries for STW GTK.

Using the SWT library

Once we've got SWT built (or just use my build from http://www.cs.washington.edu/homes/bdferris/dist/org.traditionalcake.swt.gtk.j2me.tar.gz), all that's left is to start using it. The easy part is adding the SWT jar file to your poject. The trickier part is loading the associated native libraries. Normally, the SWT class files would make the appropriate call to System.loadLibrary(). However, that method is not natively available in the J2ME profile. Instead, we need to load the libraries ourselves. Though not included in its other profiles (e.g CLDC, CDC, MIDP, etc.), the default J9 VM profile does include System.loadLibrary() support. Thus, we can add the following snippet of code to one of our classes (directly in the class body) to load the libraries:

   static {
       System.loadLibrary("swt-gtk-2130");
       System.loadLibrary("swt-pi-gtk-2130");
   }

However, remember that when you transfer code to another platform (e.g. Pocket PC), those System.loadLibrary() calls will be incorrect.

That's it. SWT should now be running natively under J9 on Linux with the same version that will be available on the Pocket PC.


A Modern Approach

All this hackery just to get J9 working with your build environment might be a little excessive. J9 is Java 1.3 compliant, so as long as you set your compliance level appropriately in your IDE, you should be ok. Be sure to code to the 1.3 apis (http://java.sun.com/j2se/1.3/docs/api/index.html), and note that useful stuff is missing (ex. regular expressions).

Note that you are also not limited to the older version of SWT included with Placelab's J9 distribution. I've run the latest SWT (3.1) as downloaded from Eclipse (http://eclipse.org/swt/) and it works like a champ. In fact, I'd probably recommend running an upgraded SWT, as there are bug fixes and better integration with Windows Mobile 2003.