Table of ContentsI Shall Call It Mini-MEMIDP

J2ME Architecture

As I mentioned briefly in Chapter 1, Sun elected to create different versions of Java to suit different environments. From the enterprise development tools designed for use in servers to the micro systems for which you're developing, each version has its own place in the Java landscape.

It's important to note that the division between platforms is not simply categorical. The line between different platforms can get blurry.In fact, J2ME development sometimes requires the use of all three platforms (J2ME, J2SE, and J2EE). For example, when you're developing a multiplayer game, you use J2ME for the client-side device software, but you also benefit from the power of J2SE and J2EE when you implement the backend server systems.

In Figure 2.1, you can see the different Java editions, along with the hardware each supports. As you can see, the various editions of Java suit distinctly different device classes. This figure also shows the three virtual machines in use for the different environments. The Hotspot VM is the default virtual machine supplied by Sun for executing the full-scale version of JavaHotspot is a newer type of virtual machine capable of dynamically optimizing heavily executed code (hotspots) during runtime. The Compact Virtual Machine (CVM) and Kilobyte Virtual Machine (KVM) are smaller virtual machine implementations designed to run within the constraints of the limited resources available on micro devices. We'll look at which virtual machine is used for different devices a little later in the chapter.

Figure 2.1. The different editions of Java suit different hardware platforms.

graphic/02fig01.gif


In developing J2ME, it was obvious that trying to fit something like J2SE on a mobile phone would be like trying to stuff the Hindenburg down your pants (oh, the humanity).

Since J2SE was obviously way too big to fit on even the larger micro devices, Sun had to shrink it down. But which parts should they remove? With such a large variety of different devices, Sun didn't want to limit all J2ME applications to the lowest compatible hardware set. This would unfairly compromise the functionality of the higher-end devices. Limiting J2ME to the capabilities of low-end pagers just wasn't a practical solution.

The designers of J2ME came up with a solution based on a revised Java architecture that provides for the exclusion of parts of the platform (such as language, tools, JVM, and API) while adding device-category-specific components. This is realized through a combination of J2ME configurations and profiles.

Configurations and Profiles

A configuration defines the capabilities of a Java platform designed for use on a series of similar hardware. Essentially, it provides for the minimization of the J2SE platform by removing components such as:

  • Java language components

  • Minimum hardware requirements, such as the memory, screen size, and processor power for the family of devices

  • Included Java libraries

Using this architecture, Sun created two initial configurations to suit the micro world one for slightly limited devices such as PDAs and Set-Top-Boxes (like digital TV receivers) and one for the "you-wanna-run-Java-on-what?!" class of devices such as pagers, mobile phones, and pets. These two configurations are:

  • CDC (Connected Device Configuration)

  • CLDC (Connected, Limited Device Configuration)

You'll review both of these in more detail a little later. The important thing right now is that these configurations let you move forward, confident of the functionality of the underlying target platform. You'll be developing for two platforms at most, not two hundred.

However, configurations don't cover everything; they merely limit Java to a suitable target platform's capabilitieswhich is essentially a nice way of saying they rip out Java's guts.

Additional functionality is required to handle the new breed of Java devices. Enter J2ME profiles.

A good example of profiles is the UI (User Inter face) for mobile phones (see Figure 2.2). The J2ME configuration (CLDC) that covers this type of device excludes the typical Java UI libraries, AWT and Swing. The devices aren't capable of displaying anything based on these libraries anyway because the screens are just too small. So there's no point to wasting precious kilobytes on them. The answer was to create a new UI suited to the specific requirements of the humble mobile's LCD screen. The resulting LCD UI is included in the CLDC profile that targets MIDs (Mobile Information Devices), hence the name MIDP.

Figure 2.2. A J2ME application is built upon both a profile and a configuration (to a lesser extent).

graphic/02fig02.gif


The LCDUI implementation exemplifies the role that profiles play in adding device-category-specific functionality. This is important because profiles provide a standardization of this functionality, rather than requiring developers to fall back to Java APIs created for each device. Figure 2.3 shows the relationship between all these components.

Figure 2.3. J2ME consists of a layer of components. The Java Virtual Machine interfaces with the configuration, which in turn provides functionality to the profile and application layers.

graphic/02fig03.gif


Now that you've reviewed the theory behind the J2ME architecture, take a look at exactly what is available within these configurations and profiles.

Two Sizes Fit All

As I briefly covered in the previous section, the current J2ME architecture provides two distinct configurations, the CDC and CLDC.

The CDC

Built for larger devices such as digital TV set-top-boxes and PDAs (typically with multiple megabytes of memory), the CDC is the bigger brother of the J2ME configurations. It contains a single profile (the Foundation profile) as well as a high-performance virtual machine known as the Compact Virtual Machine (CVM). The Java language implementation and the API pretty much have all the power of J2SE.

Sounds great, doesn't it? Unfortunately, the CDC is not available on the platform where the vast majority of micro-game players aremobile phonesso it's about as useful as a blind sumo wrestler in a midget-bar brawl.

If you want to develop games for the major audiences out there, then you're interested in those "limited" devices. Enter the CLDC.

The CLDC

The CLDC is all about micro devices, especially mobile phones. It essentially defines a standard used by device manufacturers to implement a Java run-time environment. Third-party developers, following this same standard, are then confident of the platform on which their software can run.

Developed as part of the Java Community Process (JSR-30), the CLDC configuration affects many aspects of Java development and delivery, which include

  • Target device characteristics

  • The security model

  • Application management

  • Language differences

  • JVM differences

  • Included class libraries

Take a look at each of these in more detail.

NOTE

CLDC's Pedigree

Thankfully, the CLDC wasn't developed in isolation; some of the most influential companies involved in the micro-device industry were involved in the Java Community Process expert group (JSR-30), which was responsible for the development of the specifications. Reading like a who's who of the micro-hardware industry, the list of companies involved includes

  • America Online

  • Bull

  • Ericsson

  • Fujitsu

  • Matsushita

  • Mitsubishi

  • Motorola

  • Nokia

  • NTT DoCoMo

  • Oracle

  • Palm Computing

  • RIM (Research In Motion)

  • Samsung

  • Sharp

  • Siemens

  • Sony

  • Sun Microsystems

  • Symbian

Target Device Characteristics

The first aspect of the CLDC is a definition of the characteristics a supported device should have. Table 2.1 contains a list of these characteristics as defined by the CLDC 1.0a specification.

Table 2.1. CLDC Target Platform Characteristics

Characteristic

Description

Memory

160 KB to 512 KB devoted to the Java platform (minimum 128K available to a Java application)

Processor

16- or 32-bit

Connectivity

Some form of connectivity, likely wireless and intermittent

Other

Low power consumption, typically powered by battery


NOTE

Note

One thing you might notice right away is that the characteristics of the CLDC don't mention any input methods or screen requirements. That's the job of a particular device class profile, such as the MIDP (Mobile Information Device Profile). A configuration just covers the core Java system requirements.

As you can see, the CLDC's target platform isn't exactly awe-inspiring hardware. I mean, what the hell can you do with 128 KB of RAM? And believe it or not, it gets worse.

But that's where the fun is, right? When you get into the real programming in later chapters, you'll learn how to best use the meager space you're given.

The Security Model

J2SE's existing security system was too large to fit within the constraints of the CLDC target platform; it alone would likely have exceeded all available memory. A revised model cuts down many of the features, but requires far less resources. The good news is that this simplification makes it much easier to cover all the details.

There are two main sections to the CLDC security model.

  • Virtual machine security

  • Application security

I know that security is not the most interesting subject, but I recommend you take the time to review this section. The revised security model for the CLDC lays some important groundwork for application execution models discussed later, and maybe there's a really funny joke hidden in there somewherethe world's first literary Easter egg, perhaps? Then again, maybe there isn't.

Virtual Machine Security The goal of the virtual machine security layer is to protect the underlying device from any damage executable code might cause. Under normal circumstances, a bytecode verification process carried out prior to any code execution takes care of this. This verification process essentially validates class-file bytecode, thus ensuring it is correct for execution. The most important result of this process is the protection it offers against the execution of invalid instructionsor worse, the creation of scenarios in which memory outside the Java environment is corrupted. Not pretty.

The standard bytecode verification process used with J2SE requires about 50 KB of code space, along with up to 100 KB of heap. While this is negligible on larger systems, it constitutes pretty much all the memory available to Java on many micro devices. Although I have a great desire to spend all my resources doing program verification, some rude people insist on something more, like any form of application. So in an effort to appease this demanding bunch, the CLDC specifications provide an alternative.

The resulting verification implementation within the CLDC's virtual machine requires around 10 KB of binary code space and as little as 100 bytes of run-time memory. From a dynamic memory standpoint, this is a reduction of about 1,000 times. Someone needs to get a little star stamp on the forehead for that one!

The reduction in resources essentially comes from the removal of the iterative dataflow algorithm from the in-memory verification process. The price is that you now have to undertake an additional step known as pre-verification to prepare code for execution on the KVM. The result of this process is the insertion of additional attributes into the class file.

NOTE

Note

Even after undergoing the process of pre-verification, a transformed class file is still valid Java byte-code; the verifier automatically ignores the extra data. The only noticeable difference is that the resulting files are approximately five percent larger.

A tool supplied with the J2ME development environment carries out the process of preverifying. It's all rather painless. As you can see in Figure 2.4, the important point is that the resource-intensive part of the verification process is carried out on your (overpowered) development PC (the build server).

Figure 2.4. A pre-verification process reduces the resources used for the typical class-file verification.

graphic/02fig04.gif


NOTE

Note

To avoid confusion, post-verified class files are commonly called pclasses.

Application Security The class-loader verification process discussed previously is pretty limited. Basically, it just validates that bytecode is the legitimate result of the Java compilation process. Although this is helpful, a further level of security is required to protect a device's resources.

As you might have guessed, the powerful (but rather large) J2SE security model is out the window. The CLDC incorporates a simplified security model based on the concept of a sandbox.

The term sandbox really just means that your Java code can play only within the confines of a small, controlled environment. Even if that big blue truck you love is outside and you really wanna play with it, you can't. Anything outside is completely out of bounds. So stop trying, or you're going to your room!

NOTE

Note

If you've done any development of applets (Java programs executed inside a Web browser), you're already familiar with the concept of sandbox security. The CLCD implementation is very similar.

As you can see in Figure 2.5, your code has restricted what's available in the sandbox environment. The CLDC defines a list of exactly what you can execute, and that's all you get. Protection is also in place so you can't change the base classes that make up the installed API on the devicethe so-called core classes. The CLDC specifications mandate protection for these classes.

Figure 2.5. The Java sandbox security model provides you access to core classes while protecting the underlying device.

graphic/02fig05.gif


Application Management

Managing applications on micro devices is quite a different experience than doing so on typical PCs. Quite often there is no concept of a file system, let alone a file browser. In some extreme cases, micro devices won't even store class files permanently; they delete them after you finish playing!

Most of the time, especially on typical mobile devices, users have a limited amount of application space in which to store their favorite programs. (This space will be filled with your games, of course.)

To manage these applications, the device should provide a basic ability to review the installed applications, launch an application, and then subsequently delete it if the user so desires. (Hey, don't feel badthey had to get sick of your game sometime.)

The CLDC doesn't mandate the form the application manager should take; however, typical implementations are simple menu-based tools to browse and launch programs. Nothing fancy, but they certainly do the job.

Language Differences

In the land of the little people, Java isn't quite the same as you know it. They took bits out! Brace yourself; some of them are painful.

Floating-Point Math First, there's no floating-point math. That's rightlet me say it again. You're programming games, and there's no floating-point math. The reason is that the typical micro device doesn't have dedicated floating-point hardware (which is not surprising, really), and the cost to emulate floating-point math in software was considered too great of a burden on the limited processors.

Never fear, though. In later sections, I'll show you how you can get around this. Actually, it's quite fun.

Finalization To improve performance and reduce the overall requirements, the CLDC leaves out an automatic object finalization callback. This means there's no Object.finalize method.

When using the J2SE under normal circumstances, the garbage collector process will call this method for an object it is about to discard from memory. You can then free any open resources that explicitly require it (such as open files). This doesn't mean the garbage collector doesn't run, it's just that it won't call your finalize method. Some programmers utilize the finalize method in order to free resources when an object is about to be trashed by the garbage collector. Because this method is not available, you need to rely on your own application flow to carry out an appropriate resource cleanup process. This is generally a good practice anyway. You should free resources as soon as they become available; don't leave the timing of this process up to the notoriously strange behavior of the garbage collector.

Error Handling Also for resource reasons, the CLDC does not include any of the java.lang.Error exception class hierarchy. To refresh your memory, the exceptions shown in Table 2.2 are very much of the fatal heart attack variety. There is pretty much no chance of you recovering from an error such as this; it's really up to the VM to inform the device OS, and the device OS to then panic on your application's behalf.

Table 2.2. java.lang.Error Exceptions

Exception

Description

java.awt.AWTError

Because there is no AWT in the CLDC, this isn't required.

java.lang.LinkageError

An error relating to class compilation inconsistencies. There are many subclasses of this exception, such as java.lang.NoClassDefFoundError.

java.lang.ThreadDeath

One of the only classes in the language with a remotely cool name. You don't need it, though. The application can't really do anything if it encounters this error, except maybe draw a little bomb that has exploded.

java.lang.VirtualMachineError

The virtual machine hierarchy, which includes popular favorites like OutOfMemoryError and StackOverflowError, also are not something your application can really handle.


Because these errors only occur in situations in which your application is about to go bye-bye anyway, there's no need for the CLDC to provide you with access to them.

JVM Differences

The CLDC reference implementation incorporates a revised virtual machine known as the KVM. As you can imagine, the KVM lacks some of the features of its big brother, the J2SE JVM.

The primary features that are not available as part of the KVM and its included libraries are

  • Weak referenceslets you keep a reference to an object that will still be garbage collected.

  • Reflectionthe power to "look into" code at runtime.

  • Thread groups and daemon threadsadvanced thread control (rarely used).

  • The JNI (Java Native Interface)lets you write your own native methods, which is not appropriate for sandbox development.

  • User-defined class loadersused to roll your own class loading mechanism (rarely used).

If you have any grand plans involving any of these features, you're out of luck. Thankfully, though, you can live without most of these things, especially in low-resource environments.

Of these limitations, only a couple warrant further mention: reflection and user-defined class loaders.

Reflection Reflection is the Java feature that lets your program inspect the code being executed at runtime. This means from your code you can inspect the code in classes, objects, methods, and fields. The KVM does not support reflection in any form, which also means you have no access to features that inherit their functionality from the reflection core, such as the JVMDI (Java Virtual Machine Debugging Interface), RMI (Remote Method Invocation), object serialization, and the profiling toolset.

We can live without most of these features in game development. RMI for example, which lets you execute methods across a network, isn't particularly useful since it's a little heavyweight for typical multiplayer game development. We can achieve the same level of functionality by coding a simpler system ourselves. Object serialization is something that would be useful for saving and loading game state; however, again we can code this up ourselves without too much trouble.

While the profiling toolset is also not available, the wireless toolkit from Sun does provide a more limited profiler that suits our needs. Not having the profiling tools just means you can't write your own profiling system. Likewise you won't be able to roll your own debugging system.

User-Defined Class Loaders User-defined class loaders are another feature that is removed from the KVM. These were used primarily to reconfigure or replace the class-loading mechanism with a user-supplied one. Unfortunately, the sandbox security model wouldn't work very well if you could just whack in a new class loader and circumvent the security entirely, so UDCLs got the big shift-delete. This isn't something we really use in general game development anyway.

Included Class Libraries

One of the things I love about Java is the extensive library of classes that comes with the platform. As you can imagine, though, the J2EE and J2SE libraries are too large to use on micro devices.

The designers of the CLDC faced a number of issues regarding the creation of a set of libraries to include with the configuration. The first was, of course, the key driver behind everythingresources. They had less free space than an Aussie backpacker's luggage at the end of a world tour. Some things had to go, and that naturally meant they couldn't please everyone.

This also raised the issue of compatibility, the goal being to retain as much similarity and compatibility as possible with the J2SE libraries. To facilitate this, the designers divided the CLDC libraries into two logical categoriesclasses that are a subset of J2SE and classes that are specific to the CLDC.

These classes are differentiated by the prefix of the library. J2ME classes that are based on a subset of equivalent J2SE subset classes use the same names as their bigger cousins, so java.lang.String, for example, has the same name with J2ME as it does in J2SE, it's just a reduced version. CLDC-specific classes appear under the java extensions hierarchy, javax.*. This is reserved only for classes that do not normally appear in J2SE.

NOTE

Note

CLDC-specific classes sound great, but in reality they don't exist. The CLDC specifies a single group of classes relating to connectivity, but it's not the CLDC's role to implement these; that's the job of a profile, such as the MIDP.

Take a look at exactly what J2SE functionality you have left after the CLDC culling. First, it's important to note that these classes might differ from those found in the J2SE implementation, according to the following rules.

  • The package name must be identical to the corresponding J2SE counterpart.

  • There cannot be any additional public or protected methods or fields.

  • There cannot be changes to the semantics of the classes and methods.

In short this means that a J2SE class implemented in J2ME can only have methods removed, not added, and there can be no change to existing methods (though the actual implementations of those methods could be completely differentnot something we really need to care about anyway as long as the methods work the same).

Following is a complete list of the available classes; however, this list can be rather deceiving because many of these J2ME classes have had methods removed.

NOTE

Note

One thing you might notice when looking through the CLDC class libraries is the distinct lack of a few key elements, such as any form of UI (User Interface) or access to device-specific functions. That's the job of a given device category's profile. You'll take a look at these libraries a little later, in the MIDP section.

  • System classes

  • java.lang.Object

  • java.lang.Class

  • java.lang.Runtime

  • java.lang.System

  • java.lang.Thread

  • java.lang.Runnable

  • java.lang.String

  • java.lang.StringBuffer

  • java.lang.Throwable

  • Input/output classes

  • java.io.InputStream

  • java.io.OutputStream

  • java.io.ByteArrayInputStream

  • java.io.ByteArrayOutputStream

  • java.io.DataInput (interface)

  • java.io.DataOutput (interface)

  • java.io.DataInputStream

  • java.io.DataOutputStream

  • java.io.Reader

  • java.io.Writer

  • java.io.InputStreamReader

  • java.io.OutputStreamWriter

  • java.io.PrintStream

  • Collection classes

  • java.util.Vector

  • java.util.Stack

  • java.util.Hashtable

  • java.util.Enumeration (interface)

  • Type classes

  • java.lang.Boolean

  • java.lang.Byte

  • java.lang.Short

  • java.lang.Integer

  • java.lang.Long

  • java.lang.Character

  • Calendar and time classes

  • java.util.Calendar

  • java.util.Date

  • java.util.TimeZone

  • Utility classes

  • java.util.Random

  • java.lang.Math

  • Exception classes

  • java.lang.Exception

  • java.lang.ClassNotFoundException

  • java.lang.IllegalAccessException

  • java.lang.InstantiationException

  • java.lang.InterruptedException

  • java.lang.RuntimeException

  • java.lang.ArithmeticException

  • java.lang.ArrayStoreException

  • java.lang.ClassCastException

  • java.lang.IllegalArgumentException

  • java.lang.IllegalThreadStateException

  • java.lang.NumberFormatException

  • java.lang.IllegalMonitorStateException

  • java.lang.IndexOutOfBoundsException

  • java.lang.ArrayIndexOutOfBoundsException

  • java.lang.StringIndexOutOfBoundsException

  • java.lang.NegativeArraySizeException

  • java.lang.NullPointerException

  • java.lang.SecurityException

  • java.util.EmptyStackException

  • java.util.NoSuchElementException

  • java.io.EOFException

  • java.io.IOException

  • java.io.InterruptedIOException

  • java.io.UnsupportedEncodingException

  • java.io.UTFDataFormatException

  • Error classes

  • java.lang.Error

  • java.lang.VirtualMachineError

  • java.lang.OutOfMemoryError

You might have noticed there are no connectivity classes included in this list, such as those found in the java.net.* hierarchy. Because of the interdependencies in the current communications library, connectivity classes could not be included without breaking the migration rules discussed at the beginning of this section. Therefore, the CLDC includes a framework for a new communications class hierarchy known as the connection frame work. The CLDC's cut-down framework design is exactly thata design. There are no included classes that actually implement it. For that, you look to the world of profiles.

    Table of ContentsI Shall Call It Mini-MEMIDP