Design Article
Realtime programming in Java: Part 1
Dr. James J. Hunt and Dr. Fridtjof B. Siebert, aicas GmbH
5/22/2006 12:00 PM EDT
The large standard class library also contributes to higher productivity and safety. These are benefits that save both time and money during project development, testing, and maintenance. Even critical applications could profit from these advantages.
The use of Java technology is becoming more and more popular even in areas well beyond the original scope of this programming language. Especially in critical applications in domains -as diverse as automotive, anionic, industrial automation, telecommunication, and medical, the advantages of Java are attractive. The enormous cost of a failure for such systems and the improvement in Java performance is making the performance advantages of C and C++ ever more irrelevant.
As embedded and safety critical systems become more complex, the advantages of higher productivity in the development process compared to traditional languages such as C and C-I-+ increase Java's attractiveness. Platform independence and the increased flexibility of Java through mechanisms such as dynamic class loading, also weigh strongly in Java's favor.
Combined with good object oriented design, the use of Java can eliminate the need for reimplementing the same functionality more than once. With Java Technology, the choice of machine architecture and operating system can be decoupled from program code.
Nevertheless, there are a number of drawbacks that prevent the use of standard Java implementations in embedded, realtime, and safety critical systems. High memory demand, poor runtime performance, and lack of realtime performance guarantees can nullify the advantages of Java for these systems. To address these challenges, both realtime specific Java standards and implementations are now available.
In particular, the Real-Time Specification for Java (RTSJ) ensures that a variety of implementations will continue to be available for programming embedded and realtime systems.
Inadequacies of Java for Realtime
Programming
There are two main kinds of barriers to using Java for realtime and
embedded programming: lack of determinism and limited access to the
underlying hardware. Both these issue arise in part from the goal of
ensuring platform independence.
It was easier to provide platform independence by providing minimal requirements for thread and priority behavior and to restrict access to the hardware to ease the job of implementation than to devise a rigorous definition that could be implemented on a broad range of processors and operating systems. The use of garbage collection for ensuring memory integrity tended to support the minimalist approach, since realtime garbage collection technology had not been available until relatively recently.
Garbage Collection. One of the biggest advantages of Java technology, the safe memory management through automatic garbage collection, has also been the biggest problem for the use in realtime systems. The garbage collector is a basic safety mechanism in Java and has consequently been considered to be compulsory.
Unfortunately, traditional garbage collection techniques require non-deterministic preemption of the processor to accomplish its task. Though there are now realtime garbage collection techniques, solving this problem was a major goal of the RTSJ.
The garbage collector (GC) is responsible for ensuring that all memory that is no longer in use is returned to the free memory list. In addition, GC must ensure that the memory does not become fragmented. In a classic Java system, the GC can stop all application threads at an unpredictable time and for an unpredictable duration to fill allocation requests or to move objects to reduce memory fragmentation. This leads to pauses as illustrated in Figure 1, below.
![]() |
| Figure 1: Pauses Due to Garbage Collection |
These pauses make the prediction of timing behavior of the application impossible. To permit realtime programming, one therefore needs a means of exempting realtime tasks from these pauses. The obvious solution is to break up GC activity into short intervals that may be safely interrupted. This proves to be quite tricky in practice due to the fine grain interdependency of object allocation and access in application threads and the GC process. Any realtime specification must address this issue.
Threads, Priorities, and Synchronization. Threads need to not only interact with the GC process, but also with other application threads. Ensuring realtime behavior requires a well defined thread, priority, and synchronization model.
Standard Java defines only minimal requirements for thread interaction. How priorities effect thread execution is ill defined. Preemption is not required. No mechanism for priority inversion avoidance is specified. In short, there are not guarantees about execution order in standard Java. Again, any realtime system requires such guarantees.
Device Access. Finally, hard realtime application are hard realtime because they interact with their environment in some way. Certainly, device support can be provided through JNI, but this reduces portability and opens vulnerabilities in the type system. A realtime systems specification needs support here too.
The Real-Time Specification for Java
The aim of the Realtime Specification for Java (RTSJ) is to extend the
Java language definition and the Java standard libraries to support
realtime programming.
Central to this task is the provision of threads whose execution is deterministic, while preserving compatibility with other Java environments and upward compatibility for existing, non realtime Java applications. The most important contributions of the RTSJ to deterministic execution are in the following seven areas:
• thread scheduling,
• memory management,
• synchronization,
• asynchronous events,
• asynchronous flow of control,
• thread termination, and
• physical memory access.
In addition, the RTSJ also addresses areas that are not directly related to realtime behavior, but are of great importance to many embedded realtime applications. In particular, direct access to physical memory and asynchronous mechanisms are included for supporting device access. In short, the RTSJ addresses all the issues mentioned above which prevent the use of standard Java for realtime programming.
Memory Areas. The most obvious barrier to realtime programming is the garbage collector. Pauses due to garbage collection are avoided by using the alternate facilities for managing memory provided by the RTSJ, thus avoiding garbage collection without allowing reference integrity to be violated. Threads that need to respond deterministically are only allowed to access memory not subject to garbage collection.
New memory classes, ImmortalMemory and ScopedMemory, provide these memory areas. Objects in ImmortalMemory may only be allocated, but not freed. Objects in ScopedMemory are only freed when the last thread exits the area. Since ScopedMemory areas may be nested, deallocation always occurs in reverse order of entry.
Thus, both of these memory areas guarantee that dangling and false references can not be created. The first by never deallocating objects and the second by allowing objects in a given ScopedMemory area to be referenced only by objects in the same and more deeply nested areas.
One important consequence of the use of special memory areas is, of course, that the advantages of dynamic memory management is not fully available to realtime threads. Though reference integrity is maintained, memory leaks are possible. In addition, the user must take more direct control of deallocation.
![]() |
| Figure 2: ScopedMemory Example |
Threads and Scheduling. Though using the alternate memory areas is necessary for ensuring realtime performance in an environment where the GC stops the execution of application threads unpredictably, their use is not sufficient to guarantee realtime behavior. The system must ensure both that critical tasks can preempt the GC and other less critical threads. As mentioned above, the priority of standard threads are not well defined.
![]() |
| Figure 3: Thread Interaction in RTSJ with a Standard Garbage Collector |
The RTSJ defines two new thread classes, RealtimeThread and NoHeapRealtimeThread to ensure proper preemption between both threads and threads with respect to the GC. These thread types are unaffected or at least less heavily affected by GC activity. Also, at least 28 new priority levels, logically higher than the priority of the garbage collector, are available for these threads. Figure 3, above illustrates how the new realtime thread classes can interrupt garbage collector activity.
Figure 4, below, shows an example of how the realtime threads can be used in practice. In this example, a periodic thread is created which becomes active every 200ms and writes a short message to the standard output stream. A realtimeThread implements this task. The priority and the length of the period of this periodic thread need to be provided. A call to waitForNextPeriod() causes the thread to wait after the completion of each activation for the start of the next period.
In addition to periodic release parameters, the RTSJ also supports aperiodic release parameters for managing intermittent tasks.
![]() |
| Figure 4: Periodic Thread |
Synchronization. In realtime systems with threads of different priority levels, priority inversion must be avoided. Priority inversion occurs when a thread of higher priority is blocked waiting for a monitor that is owned by a thread of lower priority.
The RTSJ provides two alternative protocols to avoid priority inversion: priority inheritance and priority ceiling emulation. The former is better for systems multi-threading performance and for systems which start thread dynamically where as the second is useful for systems with a fixed number of threads, where the priorities can be calculated in advance.
Asynchronous Transfer of Control
Sometimes it is necessary to end a task before it is completed. The
RTSJ provides an asynchronous transfer of control API for this purpose.
Any method that includes AsynchronouslyInterruptedException in its
throw clause can be ended by calling interrupt () on
the corresponding thread object. Furthermore, any code defined in the
run method of an Interruptibleobject
and started via the doInterruptible
of an AsynchronouslyInterruptedException
object can be ended by calling the fire() method
of the exception object.
![]() |
| Figure 5: Interruptible Task |
Figure 5, above, gives an example using the Timed subclass of AsynchronouslyInterruptedException. Here, some approximation method is run for a fixed time frame.
To read Part 2 in this series go to "Events, Devices and Safety Crtical Java" where the authors identify the drawbacks of conventional Java in real time systems related to events and devices, deal with real time garbage collection, and examine the safety critical portions of RTSJ and the tools for correctness verification.
Dr. James J. Hunt, is CEO, and Dr. Fridtjof B. Siebert is CTO at real time Java developer avaicas GmbH in Karlsruhe, Germany.
This article is excerpted from a paper of the same name presented at the Embedded Systems Conference Silicon Valley 2006. Used with permission of the Embedded Systems Conference. For more information, please visit www.embedded.com/esc/sv.








