Two-Part Series on Real-Time Java
Part 1 of the series introduces the concept of real-time programming and how they relate to Java. The authors describe what prevents standard Java runtime systems from being used for real-time applications:
- OS issues: scheduling delays and poor timer resolution.
- Thread priority issues: weak thread priority guarantees and priority inversion.
- Class loading delays
- Garbage collection delays
- Application code unaware of real-time requirements
- Other preemptive activities in the system
Goetz and Eckstein go on to describe one of the central concepts in the Java specification for real-time systems - the real-time thread:
In a true real-time environment, thread priorities are extremely important. No system can guarantee that all tasks will complete on time. However, a real-time system can guarantee that if some tasks are going to miss their deadlines, the lower-priority tasks are victimized first.
The RTSJ defines at least 28 levels of priority and requires their strict enforcement. However, as this article mentioned earlier, RTSJ implementations rely on a real-time operating system to support multiple priorities, as well as on the ability of higher-priority threads to preempt lower-priority ones.
The final concept covered by part 1 is the various extensions made to support memory management. Because of the delays related to garbage collection and object allocation delays, three memory realms are distinguished:
In addition, the RTSJ is designed to allow both non-real-time and real-time activities to coexist within a single Java application. The degree of temporal guarantees provided to an activity depends on the type of thread in which the activity is executing:
java.lang.Thread(JLT) threads are supported for non-real-time activities. JLT threads can use the 10 priority levels specified by the Thread class, but these are not suitable for real-time activities because they provide no guarantees of temporal execution.
- The RTSJ also defines the
javax.realtime.RealtimeThread(RTT) thread type. RTTs can take advantage of the stronger thread priority support that the RTSJ offers, and they are scheduled on a run-to-block basis rather than a time-slicing basis. That is, the scheduler will preempt an RTT if another RTT of higher priority becomes available for execution.
- Standard heap - Memory management as in standard Java.
- Immortal memory - Memory that must be explicitly de-allocated by the software.
- Scoped memory - Memory that exists for a discrete lifecycle, and has a fixed size boundary.
Even if software is using a special memory realm, however, it is still susceptible to resource-usage by GC on the other non-critical sections of the memory. For that reason, part 2 of the series focuses on the problems related to garbage-collection, describes the various GC approaches available to a real-time Java system, and then describes Sun's commercial real-time Java system: Java RTS. The four garbage collection algorithms described in part 2 are:
The RTSJ provides a subclass of RTT called
NoHeapRealtimeThread(NHRT). Instances of this subclass are protected from GC-induced jitter. The NHRT class is intended for hard-real-time activities.
To maximize predictability, NHRTs are allowed neither to use the garbage-collected heap nor to manipulate references to the heap. Otherwise, the thread would be subject to GC pauses, and this could cause the task to miss its deadline. Instead, NHRTs can use the scoped memory and immortal memory features to allocate memory on a more predictable basis.
- Work-Based GC - Collection triggered by object allocation
- Time-Based GC - Collection bound by standard time-boxes
- Henriksson's GC - Work-based GC with a distinction over critical and non-critical threads.
- Java RTS Real-Time GC (RTGC) - A more flexible/granular extension of Henriksson's GC available in Java RTS