Executing Code from ROM
Desktop JVMs usually can’t execute Java code directly from ROM. Normally, Java classes are first loaded into RAM, verified, and then executed by the JVM.
This approach is impractical for many embedded systems because it increases the use of expensive RAM beyond the cost constraints of the embedded system. A ROMizer, such as Java CodeCompact for PersonalJava and EmbeddedJava, creates ROM-based executable images of Java classes. To execute Java code out of ROM instead of RAM, a ROMizer utility processes Java class files into a runtime format that can be run directly out of ROM or flash memory by the JVM. The ROMizing process frees the JVM from the class-file loading and byte code verification phases, and improves the performance and start-up time of Java applications.
Direct Access to Memory/Files
Java includes a large set of classes that are not scalable by default. Desktop JVMs usually require several megabytes of disk space and RAM to execute. Embedded systems usually don’t have large disk drives or big memory spaces, although some of this memory usage may be converted into ROM/flash memory for diskless embedded systems. Therefore, it’s critically important that developers tailor the operating system and runtime components for embedded systems to each application to avoid unnecessary memory usage. However, it may not be easy to analyze and remove all unused classes and methods from Java to minimize the embedded application’s final memory footprint. Desktop JVMs usually download class files from a local hard drive or a file system on the network, and these resources aren’t always available to embedded systems. The best scalability that can be achieved starts with the underlying real-time operating system (RTOS) scalability and can be tracked at three different levels on the Java side. First, the JVM may be scalable depending on the services the application requires. Second, the Java classes may also be sorted and only included in the runtime system if they’re used by the application. The verbose option of the Java launcher can be helpful in the analysis of the used classes. Finally, a dedicated utility tool, such as EmbeddedJava’s Java Filter, can be used to skim Java classes and remove unused methods and fields. Developers may want to avoid loading Java class files from a local or networked file system, or use them only as an option. They can either be stored in a memory-based virtual file system (RAM, ROM, or flash) or can be converted with a “file-izer” utility tool into a C data structure that stores the class file byte-code content that’s linked to the RTOS image.
Running Java in Real Time
Java’s biggest problem with real-time execution is that Java garbage-collection algorithms are usually nondeterministic. Once garbage collection starts, it must run to completion and can’t be preempted by a more urgent Java thread. The time required for the garbage collector to run is not predictable. This characteristic creates unbounded latency in event response, a condition that can’t be allowed in real-time systems. However, even a deterministic garbage collector may not guarantee a real-time execution of Java programs. There are currently no real-time Java implementations compatible with standard Java platform specifications, even though a consortium of companies, including Wind River, have been working with Sun to define standard real-time extensions to Java under the Java Community Process (in the JSR-00001, see www.rtj.org). The best existing solution to Java’s real-time shortcomings consists of a hybrid solution. Developers can write the real-time part of an application in C/C++ for the targeted RTOS, and the rest in Java using JNI to connect the two worlds. Developers must pay careful attention to the implementation of the JVM on top of the RTOS, making sure the overall system operates in real time even when Java is running. In addition, when evaluating JVM solutions, developers must consider memory management, garbage collection and object finalization, multithreading, interthread synchronization, networking, and graphics.
Java is suited for embedded applications because it can help developers leverage business from a new perspective, especially within the Internet-access device market where connectivity, interactivity, reliability, security, and dynamic extensibility are vital requirements. Embedded devices usually have severe memory and power consumption constraints, lower processor power, real-time behavior, and other requirements that Java doesn’t usually handle well. Numerous companies offer leadership products and solutions that can help developers make Java work in embedded solutions.
Vincent Perrier is Product Marketing Manager, Java Platforms, for the Wind River Platforms Business Unit in Alameda, CA. He can be found at http://www.windriver.com