Connected device applications are networked but operate in a more restricted environment, such as telecommunications equipment. The attractiveness of Java may relate to reuse, strength of language and processor independence as well as the ability to dynamically run new applications, but the applications themselves come from a closed universe. That is, the applications come only from the service provider or developer of the Java-based system and are qualified to run only on this device subject to certain constraints, such as size or perhaps even a language subset. In general, there is no requirement to run an arbitrary Java application; therefore, these applications can experience significant performance benefits by using compiled Java instead of a Java Virtual Machine. These devices start to resemble more traditional embedded applications and are using Java as a very flexible environment. Previously, MS-DOS or proprietary run-time systems were used for these kinds of applications.
Standalone device applications are isolated and are not expected to download or communicate with other devices. In fact, these applications may be entirely static and have their entire run-time image in ROM with no capability to add applications for execution at run time. For these applications, the attractiveness of Java is largely based on Java as a programming language-essentially none of the dynamic run-time features would be used. A normal compilation process with a Java-to-machine-code compiler would be used with conventional downstream tools including a linker and so on. There would be the need to provide run-time support for the language, but that would be transparent to the user of the language.
Java itself has evolved significantly over the last two years, not only in its definition for the desktop but also as it has been targeted at embedded systems. At first, it was more or less all or nothing in terms of Java system compliance. However, this would have had a very bad effect upon embedded use since almost certainly that requirement would make Java’s size unacceptable for a wide variety of embedded applications. The definition of Java has been segmented by JavaSoft such that a number of subset definitions of the Java system are available, now making it feasible to support these smaller definitions in realistic implementations. There are now a number of defined subsets; the following two Java subsets are particularly relevant for embedded use:
* PersonalJava is well suited for the open-connected devices segment defined above. In fact, Microtec recently licensed PersonalJava technology from JavaSoft to provide a Java Virtual Machine for its VRTX real-time operating system (RTOS).
* EmbeddedJava is targeted at the standalone segment and perhaps supported via specialized Java-compliant hardware.
Even with these subsets, which obviously help in potentially reducing the hardware required to support the Java environment, there are still significant issues regarding the implementation of such subsets. Java may be new to the embedded world, but both embedded developers as well as embedded tool and operating system suppliers are well aware of the multiplicity of details in making a language and run-time system suitable for embedded use.
In the evolution of an environment such as Java from the desktop to real-time embedded use, the technical difficulties surrounding embedding Java in applications must be overcome. Poor implementations, including problems with size, performance and configuration flexibility may still limit Java’s acceptance in the embedded market, subsets notwithstanding. However, this transition from the desktop is not new and the embedded tools and run-time suppliers have tackled these issues many times before. For example, as the C language became popular for embedded use, the first compilers and tool chains suffered from incompatibility with traditional embedded needs. Frequently, the amount of disk storage space that is taken up by Java apps can actually create hard drive failures. It’s not unheard of for hard drive recovery companies to employ Java specialists just for this reason. See http://www.harddrivefailurerecovery.net.
In fact, most early compilers could not produce ROM-able code and the run-time libraries were not re-entrant or thread safe. In addition, the code output was often very space inefficient and data structures were also laid out very inefficiently, wasting considerable RAM. Over time, however, the compilers have added options for space as well as time optimizations and for data structure memory packing. Certain C++ optimizations involved enhancements to the linker to eliminate redundant code induced by using certain advanced C++ capabilities, such as virtual functions. Not surprisingly, Java implementations will have to undergo similar transformations as they migrate from desktop to embedded use.
There are a number of ways to solve any Java implementation that is designed to support a real-time application. One is to restrict the use of Java to parts of the application that do not have real-time requirements. Rather, these parts are programmed in a traditional language such as C or C++ and scheduled independently from the scheduling of Java applications.
Another approach is to redesign the underlying garbage-collection algorithm to be consistent with the real-time requirements of the application. In this case, certain language extensions may be required, possibly breaking the compatibility with desktop Java. In the end, since Java was not designed to be a real-time language, the use of Java as a concurrent language with other parts of the application supported by a real-time operating system is perhaps the most feasible approach today.
By definition, an embedded system has unusual I/O devices.
The embedded system may have the usual serial, parallel and other traditional PC parts, but should also have devices unique to the application at hand. Consequently, a Java integrated development environment for embedded systems must support cross-development capability; simultaneous C, C++ and Java support, and multithreading.
The Java user is faced with the classic cross-development situation, in which the tools and debuggers for the target system are hosted on the desktop but must connect and interact with the embedded system across some communication path. Communication from host to target, for downloading and debugging, may take place over standard I/O connections, such as serial lines and Ethernet, as well as hardware-assisted connections, such as an in-circuit emulator (ICE).
Mixed-language development and debugging also must be supported. In many cases, existing code written in C or C++ must be reused in a new application, even if the rest of the new code is written in Java. If the approach to real-time support uses the multiple-language approach, the ability to debug multiple languages concurrently also arises. In both cases the debugger has to move seamlessly among the languages used in the application.
Since Java is also a multithreaded language, the integrated development environment must support multithread debugging. This represents a new complexity not found in debuggers designed for C and C++, as both are sequential, or single threaded languages. Recently, however, high-level language debuggers have added multithreaded support because of tight integration with an RTOS. For example, Microtec’s XRAY 4.0 debugger has been extended to support multithreaded C and C++ applications, with work under way to support Java’s multithreading as well. Historically, the embedded tools industry has attacked these problems and has produced quite powerful development tools for C and C++. Microtec is currently adapting its cross-development technology to Java, giving the embedded software developer a Java-based cross-development environment.