TicTacToe on the KVM

THE K VIRTUAL Machine (KVM) started out as a research project within Sun Labs called the Kauai Virtual Machine. Initially called the Spotless VM, it was used to test limited memory JVM configurations. You can still see some remnants of this history in the current KVM—instead of applets, the KVM runs spotlets.

I demonstrate the basics of developing software for the KVM by walking through its installation, as well as the development of a simple TicTacToe application, and the step-by-step compilation and running of the game.

CLDC and the KVM
Before going off to download the KVM, you need to understand what you are after. Depending on the type of application you want to develop and the target implementation device, you may want Personal Java, Embedded Java, or the Connected Limited Device Configuration (CLDC). Each of these implementations falls under the broad umbrella of Java 2 Micro Edition (J2ME). In reaching this decision, you will invariably be bombarded with an array of confusing acronyms.

The first place to start is with J2ME itself. J2ME defines the implementation of Java for consumer and embedded devices, ranging from mobile phones to the Java Ring. To define support for all the different consumer and embedded devices, the J2ME spec consists of VMs and core APIs specified as domain-specific "Configurations" that make up the runtime environment, and target implementation-specific "Profiles" that define the API scope. So, a J2ME implementation consists of a "Configuration" and a "Profile." The Configuration contains the runtime environment and the profile defines the APIs.

The CLDC specification is the first J2ME Configuration. Representatives of the wireless-service provider and point-of-sale terminal industries developed it through a Java Community Process effort (JSR-30). The CLDC defines a complete runtime environment that targets mobile devices such as the PalmPilot. At the center of the CLDC runtime environment is the KVM. As previously noted, a J2ME implementation must have a Configuration and a Profile. The Mobile Information Device Profile (MIDP) is the first J2ME Profile. It specifies the API set for the mobile/wireless class of devices. The CLDC and the MIDP together define the J2ME implementation for mobile devices.

Getting and Installing the KVM
Getting the KVM installed and running can be an adventure in itself. Due to licensing issues, you have to obtain a source code agreement from Sun, and then download and compile the C code that makes up the KVM.

The first step is to register with Sun's Community Source Licensing program to download the CLDC. Once registered, the download is freely available as two packages from Sun's Community Source Licensing Web site. The first package, j2me_cldc-1_0-src-winsol.zip, contains the runtime platform for the J2ME CLDC and includes the necessary documentation and tools for porting TicTacToe or any CLDC implementation to the PalmPilot or other devices. The second package, j2me_cldc-1_0-src-palm_overlay.zip, contains a CLDC-compatible port for the PalmPilot and is dependent on package one being installed first. These two packages together provide the CLDC implementation for the PalmPilot. You will also need to have the JDK.1.2.2 readily available to compile the CLDC library source code during installation. The CLDC SDK is currently available only on Windows and Solaris platforms.

Once the contents of the j2me_cldc-1_0-src-winsol.zip file have been extracted, you will find the release notes, installation notes, and additional documents in the \j2me_ cldc\docs directory. It is not necessary to repeat the installation steps because the documentation is complete and easy to follow. However, note that the CLDC and SDK have been written in C and are distributed uncompiled, so you will need to download the gnu tools to run the makefiles. The instructions for setting up the build environment and building the binaries are located in a "Readme" file in the \j2me_cldc\build\Win32 [Solaris]\ directory. Among the tools provided in the SDK are the emulator and GUI classes for the PalmPilot. These are provided for convenience and are not part of the CLDC specification. If you have difficulty building the binaries, either write Sun for the binaries or find a colleague who attended the JavaOne conference and has the J2ME CD from the distribution packages.

Having completed the installation of the first package, you should follow the instructions for running one of the seven examples provided in the sample directory. This will ensure that the build and compilation have been completed successfully.

The next step is to install the PalmPilot overlay. The contents of the overlay zip file are intended to complement the CLDC installation. For this reason, the zip files should be extracted into the \j2me_cldc directory. Once this is done, you should find supplemental documentation in the \j2me_cldc\docs directory for completing the PalmPilot installation. The build required for the CLDC installation will have to be performed again. At this stage of the installation, the KVM.prc and KVMutil.prc will now be available from the \j2me_cldc\bin directory. They can be loaded onto the PalmPilot along with any of the samples, via the Palm Desktop application, and then launched from the Palm Application Launcher.

TicTacToe Application Overview
The easiest way to learn about the KVM is to write a simple application. I have chosen the game of TicTacToe to demonstrate some of the basic features of KVM development (see Figure 1).

Figure 1
Figure 1. TicTacToe application.

The application consists of three main classes: the GUI, the board, and the game itself (see the Code Page for the complete source code). There is also a simple data object to hold an x,y position.

  • TicTacToe.java—the spotlet that creates the overall UI, including buttons and dialog box handling. It also acts as the controller that communicates between the board and the game algorithm.
  • TicTacToeBoard.java—the class that paints the board, handles mouse clicks on the board, and paints Xs and Os when told to by the controller.
  • TicTacToeGame.java—the class that encapsulates the TicTacToe game algorithm. The controller calls the game and asks it for appropriate moves.
  • Position.java—the simple data object that holds an x,y position.

For MVC fans, the game is the Model, the board is the View, and the main TicTacToe class is the Controller. The algorithms are encapsulated entirely in the TicTacToeGame class, which makes it easy to change this into a two-player game or modify the algorithm. The algorithm I have chosen is an easy one to beat—it plays a purely defensive role. For a more aggressive, but still beatable algorithm, check out Arthur Van Hoff's classic Java TicTacToe game on Sun's Java Web site.

Writing the Spotlet
For the most part, KVM development is the same as regular Java development with Java 2 Standard Edition (J2SE). You have all of the usual Java constructs such as if...then blocks and for and while loops. The main differences are in the GUI classes, the event handling, and the lack of many of the common java.lang.* and java.util.* classes in the KVM. The GUI classes are very limited right now, and while some of them may share the same names as their AWT counterparts, don't expect the same methods and range of functionality.

The first step to building a KVM spotlet is to declare the class and import the libraries. Your application should extend spotlet and if you plan on using any pop-up dialog windows, you must also implement DialogOwner:


  public class TicTacToe extends Spotlet
         implements DialogOwner
The DialogOwner interface consists of one method—void dialogDismissed(java.lang.String title)—which gets called when the user closes the dialog box. A dialog box is used to display the results of a game once it is declared a tie or a win for either the human or the computer.

KVM event handling is quite awkward if you are used to the JDK 1.1 event handling model. To handle events, you must override the appropriate methods in the spotlet super class. For the purposes of this application, the only event of interest is the penDown event, so we need to override the penDown() method. Other events include penUp, penMove, and keyDown, which can all be utilized by overriding the corresponding methods:


  public void penDown(int x, int y) {
    if (exitButton.pressed(x,y)) {
      System.exit(0);
    } else if (newGameButton.pressed(x,y)) {
      resetGame();
    } else if (board.pressed(x,y)) {
      Position position = 
           board.getPosition(x,y);
      makeMove(position);
    }
  }
This method receives the x and y coordinates on the screen at which the event specified in the method name occurred. From there, you must query each of the components in the application that might be affected by a penDown event to find out if the event occurred within their boundaries. Each component must provide a boolean pressed(int x, int y) method that returns true if the x and y coordinates given are within its boundaries. The name of this method is a convention, so we use it for our component, TicTacToeBoard.


  public boolean pressed(int x, int y) {
    if (  (y > TOP_OFFSET)
       && (y < (top_offset+board_size))="" &&="" (x=""> LEFT_OFFSET)
       && (x < (left_offset+board_size))="" )="" {="" return="" true;="" }="" else="" {="" return="" false;="" }="" }="">
The TicTacToeGame class contains no KVM-specific code. The controller calls the TicTacToeGame object to get the next move for the computer, and calls the makeMove() method to update the game state with the move made by either the computer or the player. A refactoring exercise would be to remove the algorithm from the game state and put it in a different class. The new Algorithm object could then either statefully have a reference to a Game object, or else statelessly be passed in a Game object for evaluation purposes each time a computer move is wanted.

Compiling and Running the Application
There are three steps to building the CLDC application: compilation, verification, and generation. Development of a J2ME application can be done within any of your favorite editors or IDEs. IBM's VisualAge for Java was used to write TicTacToe. Once development of the code is complete, or if you want to build the code for testing, you are ready for the first step: compilation.

Compiling CLDC Java code is no different than compiling any other Java code. Simply make the call to the JDK1.2.2 javac compiler to generate class files. In the case of TicTacToe, the compiler call made in the directory where the source files are located is:


  C:\> javac *.java
Once you have successfully compiled the source code, you are ready for the second step: verification. As mentioned before, the CLDC specification defines the API set available for your applications. When you compiled the source code, the javac compiler had access to all the Java API libraries and any other libraries specified in your CLASSPATH environment setting. The javac compiler is unaware of the set of APIs the CLDC is allowed to use.

To verify that your code complies with the CLDC specification, each of the classes making up your application must be verified with the preverify tool provided in the CLDC SDK:


  C:\> preverify -d . TicTacToe
  C:\> preverify -d . TicTacToeBoard
  C:\> preverify -d . TicTacToeGame
  C:\> preverify -d . Position
Note: To run the preverifyer you must have the j2me\bin directory in your path environment.

Errors from the preverifier relate to illegal API calls outside the CLDC specification and should be addressed before generation. The preverifier does not generate any files or binaries, and thus does not stop you from attempting to build the prc file. If you do not verify your classes, the application will fail in either the prc-generation phase or within the PalmPilot KVM.

For testing purposes, you will execute the class files against the Palm emulator provided as part of the CLDC SDK. This emulator, "KVM.exe," is located in the j2me\bin directory and will run a class containing a main method:


  C:\> kvm TicTacToe
You will want to use the emulator for testing and debugging purposes when you are ready to deploy the app onto the PalmPilot. Once you have successfully verified the class files and completed the application, you are ready for the third step: generation.

Before TicTacToe can be installed onto the PalmPilot using the Palm installer tool in the Palm Desktop, the class file must be converted to a file format the PalmPilot understands. To generate the .prc file for the Palm, the CLDC SDK provides a MakePalmApp utility provided in the j2me\bin directory:


  C:\> java palm.database.MakePalmApp -icon
  tictac.bmp -bootclasspath
  C:\KVM\j2me_cldc_palm\lib\classes TicTacToe
There are at least three arguments that should be provided:

  • -icon,which specifies the directory and the name of the icon.
  • -bootclasspath,which lets the utility know where the libraries are for building the prc.
  • TicTacToe,which is the name of the class containing the main method.

Once generation is complete, you will find the prc file in the current working directory. You can use the Palm installer to install the application onto the PalmPilot.

Conclusion
KVM development can feel quite primitive if you are used to the JDK 1.1, 1.2, and now 1.3. It feels a little like working with Java in the early 1.0 alpha and beta days: Lots of bugs, but lots of fun. It can be very satisfying getting an app running on your Palm device—after you've gotten over the initial learning curve involved with developing on a new platform. However, once you've figured out the basics, you are back in the world of familiar Java coding, and you get all of the productivity benefits you're familiar with.

URLs
Sun's Community Source Licensing Web site
www.sun.com/software/communitysource/j2me/download.html

Arthur Van Hoff's classic Java TicTacToe game
http://java.sun.com/applets/jdk/1.2/demo/applets/TicTacToe/TicTacToe.java

Sun Technology Evangelist Bill Day's J2ME Archive
www.billday.com/j2me/index.html

Bugs for the CLDC and Palm overlay
http://developer.java.sun.com/developer/bugParade/index.jshtml (under the K Virtual Machine category)