The K virtual machine and the Palm V, Part 1

Java has a reputation for being big -- really big -- especially in its memory consumption, but as the new KVM reminds us, it didn't start out that way

Java started life as an operating system environment for a handheld device called the *7 ("star seven"). The *7 had only a couple of megabytes of flash memory into which all of Java and its classes had to fit. Later, when Java was targeted at set-top boxes and Web browsers, the constraints on Java's size were relaxed. When Java was released to the world in March 1995, it took up several megabytes of disk space -- even more when stored in an inefficient filesystem like Microsoft's FAT16. Today, the CLASSES.ZIP file for Java 1.1 is nearly 9 MB, and is bigger still for the Java 2 Platform, Standard Edition. How can you go from that multimegabyte monster to something small? How can you put the genie back into the bottle?

What exactly do you mean by 'Java?'

The path to recapturing the genie begins with the question posed in the heading above. The question of what exactly is meant by the word Java has been the subject of several recent court cases, and the ambiguity is not surprising. There has always been a lot of confusion around the concept of Java -- even within Sun itself, in the early days. Does the name refer to the language? Or the interpreter and the language? What about the classes that were used? If you want to discuss the size of Java, you must first have a clear definition of what exactly Java is. This question took on huge political ramifications when Sun began pushing its "write once, run anywhere" mantra -- for, in order for this statement to be true, the definition of Java had to include things, such as user interface classes, that one might not otherwise expect to be included.

A pro forma definition of Java was presented in the Java Language Specification by Guy Steele and Bill Joy. That specification included, by reference, the core set of Java classes and user interface classes that formed the basis of the Java Developer Kit (JDK) distribution. Using this definition and the JDK 1.1.8, we can arrive at a size estimate for Java that is something in the neighborhood of 10 MB of disk space! To move from there to the realm of the small -- and for PDAs and pagers you'll need something much smaller than 1 MB -- you either need better than 10:1 compression, or you need to change the question.

Making Java smaller: The Java Card and Embedded Java

Prior to the introduction of the K virtual machine (KVM), Sun had made a couple of attempts to make Java smaller, in the form of the Java Card and Embedded Java. These represent two interesting approaches to the problem of reducing Java's size, and at least one of them was fairly successful at solving the problem within its design space.

Smart cards are devices with a very small memory size, so to run Java, they have to have a very small version of the language. The size reduction in Java Card was accomplished using two techniques: the first was to limit the number of classes required to be considered compliant, (for example, there are no Windows system classes); and the second was to implement the bulk of the Java Card specification in a single kernel binary with a wrapper of Java around it.

The smart card approach to making Java small has worked well because the various things a smart card has to do are fairly well understood. Furthermore, the classes do not have to change very frequently, so having the classes implemented in the code of the native processor is a reasonable optimization. The disadvantage of smart cards is that, when the classes do change, one needs an entirely new smart card, not simply a new set of classes loaded onto an existing card.

The other notable attempt by Sun to create a smaller Java for more limited platforms was Embedded Java. This implementation was designed for devices with more storage space than a smart card -- perhaps as much memory as a modern PDA or palmtop computer. The strength of Embedded Java is that it follows the philosophy of standard Java much more closely; it has a well-defined set of standard classes and a base kernel that runs Java bytecode. Embedded Java's weaknesses are that it is too big and slow, and that it makes too many demands on the platform on which it runs. Furthermore, Embedded Java is unfortunately designed to own any platform on which it runs -- meaning that it was supposed to own all the system calls, own all the libraries, and, most of all, own all of the devices.

This approach to making Java small has not worked well, because turning over control of a device to Embedded Java is not viewed favorably by those companies, like Palm Computing, that manufacture small platforms. The platform makers see the existing software on their devices as adding value and differentiating them from other devices. Embedded Java specifies all of the user-interface widgets, all of the classes, and demands all of the platform. With Embedded Java installed, much of the differentiation resulting from the platform's software vanishes.

Due in large part to this misguided attempt by Sun at owning the platform, Embedded Java has been a complete failure (and Personal Java, for that matter, has been as well). Fortunately, Sun is a big company, and there is a part of Sun where people without corporate agendas get to implement excellent ideas. That place is Sun Labs, where the K virtual machine was born.

Making Java small without preconceptions

I must admit here and now that I have no inside knowledge whatsoever on how the Java 2 Platform, Micro Edition (J2ME) was implemented. I do, however, have the experience to recognize what constraints were put on the design. Also, the white paper (see the Resources below) on this platform does a good job of establishing what was going on in the minds of the engineers when they came up with the idea of a small Java.

The J2ME project was built from the ground up out of new code in order to be a small and fast implementation of the Java virtual machine (JVM). The new implementation was called the K virtual machine, and, according to the aforementioned white paper, its creators had the following goals in mind when developing it:

  • It needed to be optimized for small size
  • It needed to be easy to port to different platforms
  • It needed to be modular and extensible
  • Its source-code base needed to be written from scratch
  • It needed to be as complete and fast as possible without significantly increasing its footprint

The key goals in this list are that the KVM be small, fast, and extensible. The fact that the KVM was rewritten from scratch means that it doesn't carry with it any history in the form of legacy code from the Java project itself. An aspect of the KVM that isn't emphasized strongly in the white paper, but that clearly shows up in the implementation, is that the KVM runs on top of the native OS of its platform; it doesn't try to subsume that OS out of existence.

The goal of being small is easy to understand: making a program smaller means that there are more platforms available on which it can run. But the goals of being fast and extensible are less obvious.

Speed is essential when programmers don't know what sort of performance they can expect from the platform on which their software will run. Microsoft can build elegant but slow algorithms in the next generation of Windows because it can count on Intel bailing it out with a faster processor; however, the market potential of a cross-platform product like the KVM is based on the slowest CPU on which it runs at an acceptable speed. In other words, the faster the KVM, the more platforms on which it will be viable.

The goal of extensibility is essential if the uses for the platform are not fully known in advance. Smart cards, for instance, aren't that extensible in terms of class behavior, but that's acceptable because most of the things that smart cards do are fairly mundane. A more general-purpose environment, however, needs to be able to grow in directions not forseeable by the developer of the platform. For that reason, the KVM must be extensible in order for it to evolve to support that killer application of the future.

The core of the K virtual machine

The KVM core as distributed on the Palm V at the JavaOne conference has a mere 23 classes. Let's go through them in groups and show why they are there:

Group 1

java.lang.Object

java.lang.Class

java.lang.String

java.lang.StringBuffer

The four classes in Group 1 define the underlying structure of a Java program -- classes and objects -- as well as the only native Java type that isn't also a native platform type, strings. It's pretty obvious why these classes must be core: there would be no Java if there were no objects. The most notable classes are the string classes, as their presence is an acknowledgement that all KVM implementations will need to deal with strings. The inclusion of strings is one of the significant differences between this edition of Java and the Java Card implementation.

Group 2

java.lang.Thread

java.lang.Runnable

Group 2 consists of two classes, Thread and Runnable. These two classes are the multitasking model for Java and are essential to its built-in threading. They insure that objects on the KVM can run in parallel with other objects. Multiple threads are essential to the support event models that are found on many small platforms.

Group 3

java.lang.Throwable

java.lang.Error

java.lang.Exception

java.lang.IllegalArgumentException

java.lang.IllegalAccessException

java.lang.RuntimeException

java.lang.IndexOutOfBoundsException

java.lang.NullPointerException

Group 3 contains the exception classes. As Java uses an exception model for error handling, the core set of classes has to define the two types of exceptions (Error and Exception), which are both derived from Throwable. Further, the required standard exceptions are included to support the generic errors that Java programs encounter regularly.

Group 4

java.io.InputStream

java.io.OutputStream

java.io.IOException

java.io.Serializable

Group 4 has the classes that define Java's stream-based I/O model and marshalling interface. You may not initially think that Serializable is essential; consider, however, that the only way to get things in and out of most small platforms is by using a serial interface of one form or another. Being able to ship objects in an architecture-neutral form is thus not only useful, but required.

Group 5

java.net.Socket

java.net.SocketInputStream

java.net.SocketOutputStream

java.net.SocketException

Group 5 defines the objects that implement the Java networking layer. With these four classes, a Java programmer can build arbitrarily complex network protocols that are not limited by the platform and can communicate with most network services.

Group 6java.lang.RunTime

Group 6, the last group, isn't really a group at all; it is the class RunTime, which defines things that the KVM might need in order to control the underlying platform. In the case of the version distributed at JavaOne, the RunTime class controls the garbage collector and provides methods to tell classes how much memory was in use and how much was available.

User interface: The next layer

After reading the previous section, you may be thinking: "Okay, so I can write a simple Java program with the KVM. But how do I write something that interacts with a user?"

In the demonstration version of the KVM that was released at JavaOne, that question was answered by a set of classes that are included on the Palm V in the package com.sun.kjava. In the remainder of this article, we will briefly consider the classes in this package. Remember, these classes are all in the com.sun.kjava package, so mentally prepend that to the class names while you are reading.

These classes are headed by a core application class called Spotlet. The Spotlet class plays the same role within the KVM as the Applet class does in browser-hosted Java environments: it is a base class from which a new application can be derived. However, it isn't required that your Java code extend Spotlet, because the KVM application on the Palm has the ability to run any class in its class library as long as it has a main method defined statically. This ability is invoked by tapping the Run button in the KVM application when the class library is open.

In addition to Spotlet, there is a selection of widget classes available:

  • Button
  • CheckBox
  • Dialog
  • RadioButton
  • RadioGroup
  • ScrollTextBox
  • Slider
  • TextBox
  • TextField
  • VerticalScrollBar

These classes are all self-explanatory, as they closely match up with classes of similar names in the java.awt package; however, they all implement the look and feel of the Palm V.

We do run into what I consider something of a rough edge. In this particular package, two of the classes, Database and ValueSelector, are clearly specific to PalmOS. The former is a class that defines an interface to PalmOS databases, and the latter a widget for selecting numbers in a way that is very Palmlike and, in my opinion, not very generic.

Finally there is a mixed bag of classes that clearly reflect some difficulties the KVM team had in the definition of the base classes. These are:

Related:
1 2 Page 1
Page 1 of 2