This article introduces the development issues relating to thick clients with J2ME and related Java technology such as PersonalJava. It is intended for developers planning to deploy traditional thick client applications on 'consumer devices' such as mobile phones, smart phones, PDAs, and set-top boxes. It also covers material specifically of interest to device manufacturers and Original Equipment Manufacturers (OEMs).
Introduction to Thick Clients
A Recap on Thin Clients
The rather subjective term "thin client" is fairly well-known nowadays; a good example would be a "Web-based application." A thin client doesn't require the developer to design and write the software that runs directly on the client device. Instead, they typically use the features of a browser or some other host application in order to present and manipulate the application data. The real "guts" of the application is actually server-based, which means it can be managed and upgraded centrally.
Note: I have used Web-based applications as an example of thin clients as these are probably the most common.
Figure 1 illustrates the main architectural features of a thin client.
As well as reducing client development time, this approach also provides a potentially more efficient deployment mechanism. Anyone with a supported browser can use the application without having to install it in the conventional way. Instead of having to install it via a CD-ROM or downloading via the Internet, the user just enters the URL for the application and performs a refresh if necessary. This can solve many of the expensive and time-consuming upgrade and management problems usually associated with thick clients.
An application implemented as a thin client can mean that there is less control over the look and feel; the user interface may seem inconsistent when browsers from different vendors are used. The thin client may have to be developed for the "lowest common denominator" or may have to manage specific features of different browsers. Moreover, there is a risk that it may be susceptible to browser incompatibilities, idiosyncrasies, or bugs. Browsers from different vendors may support different versions of markup and scripting languages.
A thin client also presents a number of restrictions. For example, it is usually not possible to directly access the device's storage area, built-in device applications, or other device resources.
Although it's often stated that a thin client is easier to deploy and upgrade due to its thin Web nature, it does not escape real-world problems. In order to run a thin client, we may have to reconfigure the browser or even reinstall the latest browser release. This may be necessary if a thin client requires the browser to have the up-to-date Java plug-in, allow cookies, or add digital certificates; the list goes on. Many larger companies have strict heavyweight security policies and busy support workloads, and departments may not even have browsers or have predated and different versions. Upgrading these and configuring them for a new thin client is no trivial matter, especially for mobile devices that are out in the field being used by mobile professionals.
Table 1 shows the main advantages and disadvantages of Web-based thin clients.
Table 1: Advantages and disadvantages of Web-based thin clients
What Defines a Thick Client?
The rather subjective "thick client" is what many application developers will have already developed on numerous occasions. It is a tier one application designed with a specific task in mind, and is installed directly onto a desktop machine or mobile device. It may use open standards-based protocols such as HTTP or CORBA, but generally it does not use a markup language such as HTML for application presentation. The thick client application alone is usually responsible for presenting the data via a user interface. In contrast to Web-based thin clients, which use a browser to deploy functionality, a thick client must usually provide most of the application features itself. A suitable example is that of a Web browser. The Web browser is very much a thick client, whereas the Web applications that run within the browser can be regarded as thin clients.
Figure 2 illustrates the main architectural features of a thick client.
Why Develop a Thick Client?
A thick client has a number of advantages over a thin client. In most cases the advantages have to do with the higher level of control that can be gained over the device. As we are not relying on the constraints and restrictions of a hosting browser application, we generally have more freedom to develop a user interface embracing the device's full user interface offerings, thus allowing a more "at-home" feeling for already experienced users of the device. Device features such as file system/storage system, built-in applications and other resources, such as infrared or Bluetooth, are usually more accessible if we specifically design the application for the device or device family. This may be very important in the case of a PDA; the built-in applications may be what make the device so useful; failing to integrate with these may limit the usefulness of your application. Additionally, the application can generally be better controlled and made more robust as it is not relying on browser bugs or idiosyncrasies.
It can be argued that, for more frequently used, complex or business critical applications it is usually a better idea to develop a thick client.
Table 2 shows the main advantages and disadvantages of a thick client.
Table 2: Advantages and disadvantages of a thick client
How Would a Java Applet Be Defined -
Thick or Thin?
We have now made some reasonable definitions for a thick client in contrast to a thin client, but where would an applet fit into these definitions? An applet is a small Java application that is anchored to an HTML Web page. When we select the link, the applet is downloaded, verified, and run within the browser and the JVM - that is, if our browser is configured to allow this. This is done every time we select the applet link.
Since an applet is Web-based and runs within the constraints of a browser, it is more thin than thick. Another important giveaway is that the user does not have to install it; the applet is downloaded automatically by the browser when the user selects the appropriate HTML link and does not run directly on the device. It is, therefore, reasonable to suggest that an applet is thin. Or, maybe it's a thick thin client!
Why Use Java for Thick-Client Development?
Productivity and Reduced Risk
Most Java developers who have used other development environments, such as C and C++-based ones, prefer Java for a number of reasons, including the increase in productivity and quality. Although good quality software can be, and is, developed in other languages and environments, it requires more skill and effort, which obviously means higher costs. Java is a "clean" object-oriented language that doesn't inherit the legacy of C and strips away the often misused parts of C++. Commonly required features, such as threading and synchronization, are built into the language itself, and an appropriate garbage collector, when understood properly, usually means fewer memory leaks and is suited to most environments.
Prior to PersonalJava and J2ME, developing software for mobile devices usually involved C or C++ or proprietary languages and toolkits. While some of these toolkits were and still are very productive and appropriate, some were a developer's (and Project Manager's) nightmare that required previous experience and a few "battle scars." Java's predecessor, OAK, was originally designed specifically to address such problems with consumer device development. Before Java, just attempting to deploy the same thick-client application on a different device imposed many risks, high costs, and delayed time to market. Thus, applications were and still are often targeted at one or two mobile devices; some would argue that this can limit the success of the application and also the device.
There should be less need to understand the intricacies of the target devices. Once a thick client is J2ME CDLC-compliant it should work well on any device that supports that configuration and has the appropriate Profiles installed and any additional packages. (I'll talk more about J2ME, Configurations, Profiles, and PersonalJava in a follow-up article.) Java provides an abstraction layer between the platform and our application, and because it's ostensibly more open (while under the control of Sun), it helps save us from becoming the victim of the vendor lock-in anti-pattern. If we have problems with a bought-in application or component, it's much easier to exchange it for another. As Java is platform-independent, it means that we will need to "adapt," rather than port, an application for a different mobile device. It means that we can reuse our existing skills without having to learn radically different proprietary development environments just because we want to deploy our application on a new device.
Dynamic linking means that a class need not be loaded and linked until it is actually required. This is ideal for many application environments and allows for more efficient use of resources.
Built-In Security and Integrity
Java does automatic runtime checks such as array bounds checking, null reference checking, and legal cast checking. Arrays are automatically initialized. Synchronization is built into the language. Security management and class verification are also integral.
More Open with Well-Defined
Along with the core Java editions, numerous standard extensions are available. These extensions are defined by Sun with industry input via the Java Community Process. The APIs are well-known and well-documented, with ample examples and tutorials to springboard development. The developer is less open to risk of vendor lock-in and, depending on the extension, can replace an implementation with a better one with minimal impact.
When developing applications with Java, there are a number of common risks that may manifest themselves in embedded or real-time environments. Actually, these are not "Java" risks per se; they are risks associated with JVM implementations and their adoption within restricted environments. Here are the main ones I've come up against:
- User interface responsiveness
- Memory requirements
- Memory management - the Garbage Collector
- JVM selection
Java may be considered "slow" for a number of different reasons. This may be due to Java features such as runtime checks, security checks, dynamic binding, synchronization, and garbage collection. However, another contributing factor here is the way it is traditionally executed, with a JVM interpreter. Don't be fooled; software interpretation is by an order of magnitude slower than machine code executing on the same processor. Many Java implementations rely on this approach to executing the Java byte code, and while it is suitable for many environments, it may not be for others. As we shall see later, most mobile devices will have limited processing power in terms of a lower clock speed in order to reduce battery power consumption. Where the use of a JVM interpreter may provide acceptable performance on the same processor running at a higher clock speed, it may well struggle at a reduced clock speed. So, depending on the device and the application it may be possible to reduce much of this risk if there is the option to use some form of target compilation, for example, JIT compilation or ahead-of-time compilation.
JIT compilers will compile the byte code to the target machine code while the application is being executed. However, there is little point in compiling byte code that is seldom executed, as this will affect the overall performance of the application and introduce "code bloat."
Ahead-of-time compilation involves compiling classes during development. These may be the core Java classes, the application classes, or hot classes picked out by the developer in order to best manage the performance/memory overhead trade-offs. The classes may then be linked with the JVM in order to provide the required performance boost.
Unfortunately, though, while compilation (via JIT, Hotspot, ahead of time) may reduce the speed risk, it may inadvertently introduce other risks such as higher memory overhead, and power consumption and complexity. Compared to RISC and even CISC machine code, Java byte code is very abstract. It is machine-independent and is based on the concept of a stack-based machine interpreter instead of a register-based one (mainly for portability reasons). As such, Java byte-codes can represent more functionality in less space than their machine code equivalents.
Ahead-of-time compilation also introduces another potential problem. It reduces the portability of the application. If we want to deploy an application on a number of devices, we will need to produce separate binaries for each target device. Therefore, unless we are prepared to produce and maintain separate binaries for each target, ahead-of-time compilation may not be suitable. It is for this purpose that the JIT compiler was invented - to provide the benefit of both machine independence and run-time performance!
As memory becomes more compact and less expensive, compilation will probably become more widespread on mobile devices. In addition, JVM chips become much more popular as Java becomes more ubiquitous in embedded and soft real-time systems. Many believe it's the next logical step for JVM chips to "blossom" and become more popular in order to improve performance, increase quality, and reduce costs and power consumption. Shifting the software JVM risk as a hardware concern will soon be the norm for most consumer devices, and is planned as the next generation of JVMs for many device manufacturers. An example of this is the Moon Java processor (www.VulcanMachines.com).
User Interface Responsiveness
This factor is related to the issue of speed discussed above. Of course, the perceived speed of the user interface is of great importance. It has a huge impact on the overall usability and perceived quality of the application. These two issues can be addressed in much the same way as the speed issues. However, it is also worth noting that the application may not need to be lightning fast in order to have a responsive user interface. A device may not need to be fast at all in order to give the user the perception of speed. For example, the user should have immediate feedback from the user interface where possible.
Many Java implementations have previously been criticized for being memory-intensive. To be fair, this has usually been due to the JVM or JIT compiler. Remember, we may be running not only our application but a Java byte-code interpreter or a just-in-time compiler as well.
It is also worth noting that if you do use the traditional byte code interpreter in favor of a faster JIT compiler, the memory requirements are likely to be lower. Java byte code is an abstract stack-based intermediate code. As such, it can do a lot more in less space than real target machine code, especially if you're using RISC-based CPUs. However, there will be a price to pay - speed.
RAM also needs to be set aside for the JVM's internal dynamic data structures, such as the constant pool entries and C stack. The Garbage Collector may also need a large chunk of RAM depending on the internal algorithms used. Most of this is often unnoticed on a desktop machine where ample RAM and virtual memory are available, a luxury that consumer devices don't have.
There may be only a flash-based file system in which to store JAR files, application data, and other resources. The executable JVM or compiled code may be burned into flash ROM and executed directly from flash ROM, while using RAM for stack and heap space only. However, we may only have RAM available; in this case, we have a block of RAM that is to be used for the JVM code, heap and stack space, and also storing JAR files and other resources. Thus, the limited RAM we have is also taking on the burden of a desktop machine's hard drive.
Thankfully, with the increasing memory available in small devices, the memory risks should become less of a problem.
As previously mentioned, the use of Java chips should become a very attractive alternative in order to mitigate the risks associated with software-based virtual machines. Ahead of time, just in time or any other type of compilation is simply not necessary as the Java chip directly executes the Java byte-code; this means that portability is maintained while executing the majority of byte-code similar to how a regular CPU executes machine instructions - fast. This reduces the amount of memory required by obviating the need for interpretation or on-the-fly compilation. It also means that compiled target binaries don't need storing. Because all this "heavyweight" processing is reduced, it usually has the advantageous side effect of reducing power consumption. An example of this technology is the MOON Java chip for deeply embedded Java solutions. See www.VulcanMachines.com.
Memory Management - Garbage Collection
When developing a Java thick-client application for a desktop environment with a powerful high-speed processor, 256MB or more of RAM, virtual memory, and a mass of hard disk space, it may be possible to ignore the implementation details of the garbage collector. The chances are that in this type of environment any idiosyncrasies will go unnoticed; the machine will usually be re-booted at least once a day. With most consumer devices such as smartphones, PDAs and set-top boxes, however, this simply is not an option.
If you are a device manufacturer or OEM then understanding the implementation details of the Garbage Collector is imperative. If you a thick-client developer, then knowing how the garbage collector will behave (and thus affect your program) is also important.
If you're a device manufacturer or OEM, then you will probably have to decide which JVM implementation to integrate. An increasing number of JVMS are being marketed at the embedded and "soft" real-time industry. However, it is imperative that these are properly evaluated and understood before making the deal. This may seem a somewhat na´ve statement, but it's surprising how many decisions are made solely on marketing information and so called "strategic alliances"; hence, usually the marketing and selling of any product is geared toward people who hold the purse strings.
The golden rule here is: be wary of what you are told, no matter which badge it has been stamped with or how glossy the marketing brochures are. JVM slection will be a pivotal decision that will have a bib impact on the success of your project.
Developing for Consumer Devices
So, if we're used to developing Java applications for the desktop environment, what differences are there when developing for consumer devices? Here's a list of the more important ones. The important thing to remember is that we are no longer developing for a desktop or server environment. We are developing for a restricted, embedded and possibly real-time environment.
- Memory availability
- Less processing power
- User Interface restrictions and differing metaphors
- Battery power
- Higher reliability requirements
- Lack of file system
As discussed earlier, we know that we have less memory on a wireless device. On a desktop PC we may be used to 256MB or more of RAM. On a mobile device we may have anything from 1/2 MB to 64 MB. This means we need to respect the memory available, be realistic when specifying requirements, and take care when designing, coding, and testing our application. We may have to place more emphasis on profiling, optimizing and garbage collection validation.
In order to help use our RAM wisely, we may be able to filter out unused classes, pre-load classes, and execute the JVM and application directly in flash ROM.
Less Processing Power
Compared to a desktop PC, the processor is likely to run at a much lower clock speed and provide far fewer MIPS, in order to conserve the limited battery power. On the other hand, most users will still compare our application's responsiveness to that found on a desktop machine.
The user interface of a mobile device is likely to be a major limitation. The interaction model may be very different from what the developer is accustomed to in a desktop environment. The user interface components available are likely to be as limited as the available screen real estate and resolution and display quality. The interaction metaphor may be very different; other input methods may be used, such as a stylus, numeric telephone keypad or soft keyboard. Thus, a developer will have to have a "mind shift" in designing and developing the user interface for a mobile device and fully understand the look and feel of the device.
Unlike the thick-client application running on a desktop connected to a high-speed network, we may only have GSM or SMS connectivity. In the case of a paging device, we may be restricted by the number of characters we can send per month and only be able to communicate with the server using asynchronous two-way paging messages. We are also likely to have application protocol restrictions. For example, we may only have sockets or a paging protocol rather than RMI and HTTP. It's normal for the connection to be unreliable; if too many users are on the network our connection may be dropped halfway through a transaction. In the mobile world this is "normal" behavior that needs to be handled as such.
A mobile device, due to its very nature, will spend most of its time relying on battery power. For this reason, the clock speed is usually very low. The application developer can do other things in order to preserve power, such as making applications easier to use and allowing information to be retrieved quickly.
Higher Reliability Requirements
A mobile device, obviously, needs to be available when the mobile professional needs it. The user doesn't expect to have to reboot the device if they want to call the emergency services. Due to the limited resources, memory leaks or other memory-related problems are likely to manifest themselves very quickly on a mobile device, drastically affecting its usability and therefore its success.
Lack of File System
Many mobile devices lack a filing system or may rely on a Flash filing system. Flash filing systems have a maximum number of writes and need careful management to maintain reliability. Fortunately, this is usually provided by the Flash driver. Some mobile devices may not have a filing system at all and a database may be used in its place. As a device manufacturer developing a closed mobile device you may have to build the Java thick-client byte-code as part of the JVM and define entry points for your applications. However, if you're in the majority and developing an application for an open device, then either a filing system or an alternative database will usually be available.
This first article in a series looking at the development issues associated with mobile thick clients and J2ME has started by clarifying the general differences between thick clients and thin clients, while also attempting to define the somewhat subjective terms thick and thin. I then looked at the great advantages of using Java technology for developing thick clients for mobile and consumer devices, before balancing this with the potential risks that may be associated with particular Java implementations in restrictive environments. Developing for mobile and consumer devices in contrast to desktop and server environments was then highlighted.
In the next article I'll take a look at Java Editions, in particular J2ME and Personal Java, and also at some of the issues involved in user interface development and architectural design of mobile Java thick clients.
Why might a Vendor Provide Only a JVM Interpreter?
As previously stated, there is no obvious or best-fit execution method for Java. There are numerous variables and trade offs. However, the reasons why ahead-of-time compilation or JIT compilation may not be available may include the following:
- Developing a JIT/Hotspot compiler for the embedded and real-time world is very difficult. Many mobile devices simply won't be able to afford the extra memory requirements and processing overhead necessary for compilation.
- Vendors usually develop an interpreter first in order to prove the technology and gain experience with JVM development. They then move on to the more sophisticated execution models.
- For some mobile devices, ahead-of-time and JIT technology is just too heavyweight, and a traditional interpreter is more appropriate. For example, if a regular mobile phone is more likely to support very simple applications, then an interpreter is wholly appropriate.
Glenn Coates has been a practicing software engineer for seven years. For the last four years he has worked with mobile devices and Java, developing products such as smart-phones, micro-browsers and digital set-top boxes. Glenn holds a BSc (Hons) degree in computer science and is also a Sun-certified architect for Java Technologies. He works for Vulcan Machines developing J2ME Java chip technology. He can be contacted at: [email protected]