Java Embedded Real-Time Systems: an Overview of Existing Solutions M. Teresa Higuera-Toledano and Valerie Issarny INRIA-Rocquencourt Domaine de Voluceau-Rocquencourt 78153 Le Chesnay cedex, France
[email protected] Michel Banˆatre, Gilbert Cabillic, Jean-Philippe Lesot, and Frederic Parain IRISA-INRIA Campus de Beaulieu 35042 Rennes cedex, France
Abstract Java is a programming language with features not found in traditional languages such as platform independence and dynamic loading. Because of this, Java is extending and beginning to be used in many new environments. In particular, the advantages that Java provides make it a good candidate for distributed, real-time and embedded systems. However, Java presents some problems regarding its use in embedded and real-time environments. In this paper, we examine the state-of-the-art in the development of embedded realtime systems using Java. We analyze the limits that the Java language and its execution environment present to develop real-time and embedded systems, and we present current research in this area aimed at solving these limits.
1. Introduction The interdependence between functional and real-time semantics of real-time software makes its maintenance especially difficult. In addition, embedded software systems are not portable as they depend on the particular underlying operating system and hardware architecture. The Java environment provides attributes that make it a powerful platform to develop embedded real-time applications. Since embedded systems normally have limited memory, an advantage that Java presents is the small size of both the Java runtime environment and the Java application programs. Dynamic loading of classes facilitates the dynamic evolution of the applications embedded in the system. Additionally, the Java platform provides classes for building multithreaded appli This work has been partially funded by Texas Instruments
cations and automatic garbage collection, these make Java a good environment to develop embedded real-time applications. However, it does not guarantee determinism nor bounded resource usage, which are needed in this type of systems. Some solutions have been proposed to solve the shortcomings of Java regarding its use for embedded real-time programming. The Requirements Group for Real Time Extensions to the Java Platform, that works under supervision of the National Institute of Standards and Technology (NIST), is examining the requirements for the standard Real Time Java extension (RTJ), and has produced a basic requirements document [2]. We have studied two categories of solutions: those solutions based on the NIST document, and those that were introduced before. Solutions that comply with the NIST requirements are API-based extensions. There are four proposed solutions. i The real-time API v0.2 [9] is a Sun preliminary proposal for the RTJ specification. This extension is minimal and confined into the javax.realtime package. ii The Real-Time Specification for Java, v0.8.1 [10] gives a new and very different specification for this package. In the following we call these solutions RTJ-02 and RTJ-08, respectively. iii The RealTime Core Extension for the Java Platform (RT Core) [5] consists of two separate APIs: the Baseline Java API for non real-time Java threads, and the Real-Time Core API for ˆ specification [6], real-time tasks. iv The Basic RT JavaO a very simple extension, is presented as an alternative or a complement to this last solution. There are some API-based solutions that were introduced before the NIST document. The simplest one is the Real-Time Java Threads (RTJT) [7], a prototype that introduces tasks support. Another proposal is the Portable Executive for Reliable Control (PERC) [8], that subdivides
into two packages: the Real-Time package provides abstractions for real-time systems, whereas the Embedded package provides low level abstractions to access the hardware. This solution is closed to RT Core, which is actually an evolution of PERC. Finally, a very different solution is the Communication Threads for Java (CTJ) [4], that is based on the the CSP algebra, the Occam2 language and the Transputer microprocessor. Another type of solutions is to integrate the JVM into the operating system. This approach is undertaken by GVM [1], a prototype centered around resource management. Another option to improve Java performance is to integrate the JVM in a microprocessor. As an example, we study picoJava-I [3] that is a standard specification for the design. An implementation is the JEM-1 microprocessor of Rockwell Collins. In this paper, we review these proposed Java solutions considering and analyzing the following embedded realtime issues: solutions to access the underlying hardware (Section 2), what is the most adequate model for real-time thread scheduling (Section 3), how to solve the priority inversion problem (Section 4), how to generate and handle asynchronous events (Section 5), how to manage resources (Section 6), and how to modify the garbage collection in order to make it compatible with real-time tasks execution (Section 7). Finally, we offer some conclusions (Section 8).
2. Accessing hardware Embedded systems require close integration of software and hardware. We need to access the underlying hardware directly if we want to implement device drivers, interrupt handling or access directly physical memory. The platform independence that Java offers means that the Java language does not directly support calls to explicitly access the underlying hardware, and the Java security model requires memory to look like a black box. Java permits accessing the hardware using native methods (e.g. compiled C code or assembly) which is not portable and not secure like bytecodes. In the following, we give an overview of how solutions, introduced previousl,y solve this problem. RTJ-08. The RawMemoryAccess class allows byte level access to physical memory (e.g. getBytes() and setBytes()), mapping objects into RAM or flash memory, dealing with virtual memory (e.g. map(), umap(), and getMappedAddress()), and implementing device drivers, memory-mapped I/O, and low-level software. RT Core. Several classes extend the CoreObject class allowing to develop device drivers. The Interrupt class allows binding a InterruptTask object to a hardware interrupt. The IO abstract class provides common functionality for accessing memory and memory-mapped I/O. The
DeviceRegistry class represents permission to access a device resource, and the DeviceCapability class allows to restrict their shared access. ˆ This solution presents two classes to deal with RT JavaO. the hardware: the interrupt class that has the setActiveState() method to enable or disable an interrupt event, and the IO Capability class that is still under definition. PERC. The Embedded package provides abstract representation for the system interrupt vector, interrupt service routines, and I/O channels (e.g. ISR, Interrupt, and IO classes). Also, like RT Core, PERC presents the DeviceRegistry and the DeviceCapability classes. CTJ. In this channel-based solution, the System class contains all the system-dependent methods. The LinkDriver class provides internal and external communication. The first is by shared memory, the second is done by peripherals allowing tasks to communicate through TCP/IP sockets by rendezvous. In this way we can easily transform a concurrent program in a distributed program. picoJava-I. This microprocessor directly executes the Java bytecodes instruction set and the extended bytecodes, intentionally omitted by JVM designers. These additional bytecodes allow to control the hardware and to access the memory, and cannot be interpreted by the JVM. No program making use of these instructions will run on other platform. ˆ is under definition, and Discussion. Whereas RT JavaO RTJ-02 does not present any other solution than using native methods, all other proposals include support for accessing the hardware. RTJ-08 gives a simple but complete solution, providing a single class allowing access to physical memory, virtual memory, and memory-mapped I/O. Similar to this solution, but more complex and not supporting virtual memory is the solution provided by RT Core and PERC. There are only two differences between the extension to the API presented by RT Core and PERC to accessing the hardware. One difference is the ISR class that PERC presents, but not RT Core. The other difference is that in PERC, all the classes for embedded systems are collected into the Embedded package, which separates them from the RealTime package for real-time processing. This makes PERC different from all the other API-based solutions that provide a single package. An interesting solution is CTJ that provides a class to abstract peripheral drivers allowing transparent distributed programming. In GVM, access to physical entities is made by a proxy object offering a complete
independence with the underlying hardware. picoJava-I improves the performance of Java bytecodes, but the native code may incur a penalty. A solution is to use a Java microprocessor as bytecode accelerator for a general purpose CPU. Regarding the key concern of Java portability, the standard RTJ should abstract operating system and hardware dependencies. Hence, an API-based solution must be preferred since it avoids dependencies with the underlying platform. In this sense, RTJ-08 support a minimal but complete solution, PERC a modular solution, and CTJ a transparent solution. On the other hand, the advantage of a hardwarebased solution is the integration with the hardware platform, which enables efficient execution.
3. Scheduling A static scheduling algorithm for periodic and independent tasks is the Rate Monotonic Scheduling (RMS). This is a preemptive algorithm that assigns higher priorities to tasks with shorter periods. In other algorithms such as Earliest Deadline First (EDF), priorities are assigned to tasks according to their deadlines. The advantage of a prioritybased assignment scheme is that the scheduling overhead is low, because it is designed to prioritize the interrupt handling system, and the priority mechanism is often supported by the hardware. Hereafter, we give an overview how tasks are defined and scheduled in studied solutions. RTJ-02. The RealtimeThread class, a subclass of the Thread class, implements real-time functionalities. Each real-time thread is a task, and relates to a RealtimeThreadGroup object, which defines an activity. There are 128 priority levels and the scheduler is preemptive and priority based. RTJ-08. The RealtimeThread class extends the semantics of the Thread class for real-time. An instance of the Scheduler class implements a scheduling algorithm, providing flexibility to install an arbitrary scheduler that requires at least 28 priorities. Base scheduling is preemptive and priority-based. RT Core. This solution provides two different APIs, which address two distinct domains. Whereas Java threads are in the baseline domain, the CoreTask class extends CoreObject, that is the root of the core domain. The scheduling is priority-based and preemptable, having 128 priorities levels; highest are for interrupts handlers. ˆ The additional constructor ThreadRT JavaO. Group(String name, int RT) creates an activity.
The RT parameter marks the ThreadGroup as an activity object. This proposal assumes that all tasks and Java threads are directly mapped onto the tasks of the underlying RTOS. Real-time tasks have priorities higher than 11, the GC has priority 11, and Java threads from 1 to 10. PERC. The Real-Time package provides the Activity class and the RealTimeTask abstract class. Each activity can implement its own scheduler (e.g. EDF), the base implementation uses fixed priority. Each task can have an upper bound of jitter, a value 0 means that the task is hard real-time. The maximum jitter value is -1 and it indicates that the task is soft real-time. RTJT. This prototype enables several scheduling policies (e.g. EDF and RMS). The RtThread class extends the Java Thread class giving support for tasks. To create a periodic task, we must create an instance of the RtThread with the following attributes: priority, start time, period and deadline. If we omit the period, we create an aperiodic task. CTJ. In this solution the task scheduler is in the application domain. The PriParallel class allows definition of tasks. Each task has a priority which is given according to its declaration order. The maximum number of priorities is 8, where 7 low priorities are for user processes and the highest is reserved for system tasks (e.g. garbage collection, or other PriParallel activity). GVM. This solution combines the Java thread group hierarchy with the CPU inheritance scheduling protocol. Each thread group is an activity and has a scheduler associated. Several scheduling policies are offered (e.g. lottery, fixed priority, and RMS). Discussion. A normal way to implement real-time tasks in Java is to extend the Thread class to support real-time functionalities. This approach is undertaken by RTJ-02, RTJ-08, and RTJT solutions. Whereas in other solutions, RT Core, PERC, and CTJ, a task is derived from a hierarchy distinct from the Thread class. In PERC, the RealTimeTask class is an Object subclass. In CTJ, a task must implement the Process interface that, like Thread, defines a run() method. But the most distinct solution is RT Core, where tasks are in a different API domain than threads. A simple solution that allows maintaining the comˆ where a patibility of tasks with Java threads is RT JavaO, task is a thread object with a special attribute indicating that it is a real-time thread. All studied solutions present a static priority-based scheduler. Some solutions, RTJ-08 and RTJT, also present an EDF scheduling. Whereas in some others, PERC and RT
Core, we can implement an EDF scheduling as an option. A special scheduler is proposed in CTJ, where priorities are fixed according to the order in which the user declares the tasks. The number of priority levels for tasks in RTJ-02, RT Core, and RTJT is 128, whereas RTJ-08 allows lower cost for resource constrained by using only 28 levels as a minimum. A different solution is given by CTJ that allows only 8, but we can use the highest priority level to further add another 8 priority levels, and so on. Then, the number of priority levels is not limited. Whereas in CTJ, the GC priority level is set by the user, in most solutions (e. g. RTJ-08, ˆ the GC has priority 11 and tasks have RTJT and RT JavaO) priorities higher that 11.
4. Synchronization Java monitors present the priority inversion problem. Protocols, such as Priority Inheritance and Priority Ceiling, provide a solution to this synchronization problem. The priority inheritance protocol presents a problem: it does not prevent deadlock when a chain of blocking can be formed. The priority ceiling protocol avoids this by assigning a priority ceiling to each semaphore associated with a critical section, but it is more complex to implement. There is another problem in Java monitors: there is no guarantee about the queuing policy. This behavior must be made deterministic in the RTJ extension. How studied solutions avoid both problems, is presented below. RTJ-02. The BoundedMessageQueue class, the lock abstract class and its subclasses, BinarySemaphore, CountingSemaphore, and ReentrantMutex, provide inter-task communication and synchronization operations. By default, waiting threads are queued in FIFO order, but this policy may be changed into priority order. RTJ-08. The semantics of the synchronized keyword has been extended to avoid priority inversion, and waiting queues are priority ordered. The MonitorControl superclass abstracts monitor control policy and the monitor policy is implemented by its subclasses (e.g. PriorityCeillingEmulation and PriorityInheritance). RT Core. The SignallingSemaphore, the CountingSemaphore, and Mutex classes support synchronization between tasks, threads and the native domain. By default, waiting queues are prioritized and the protocol is priority inheritance. Optionally, objects can use the priority ceiling protocol by implementing the special core interface PCP.
ˆ The BoundedSemaphore class impleRT JavaO. ments a counting semaphore with the priority inversion protocol (the priority ceiling protocol may be added). This class is the only synchronization mechanism, and allows notification between tasks, threads and interruptions. In the p(int timeout) method, the timeout value specifies the maximum waiting time for a real-time task1 . PERC. This solution introduces two new statements as synchronization mechanisms: timed and atomic statements. A timed statement includes an upper bound on the amount of CPU time consumed to run the body of this statement2 . The body of an atomic statement must be execution-time analyzable3 , and must be executed without preemption effects. CTJ. In this model, task communication and synchronization is realized using the Channel class. Basically, communication between two tasks is given by rendezvous. Since channels are scheduled in a non-preemptive way, a channel with a buffer of only one place and with a rate monotonic priority scheduler can solve the problem of priority inversion. Discussion. Most studied solutions use the priority inheritance protocol to avoid the priority inversion problem and have priorities in waiting queues (e.g. RTJ-02, ˆ In the RTJT prototype, RTJ-08, RT Core, and RT JavaO). the priority inheritance protocol is implemented using the rt mutex lock and rt mutex unlock primitives of RT-Mach, making it dependent of the underlying RTOS. RTJ-08 and RT Core further allow the priority ceiling protocol. In RTJ-08, priority ceiling is an option, whereas in RT Core we must implement an interface. CTJ uses a different mechanism to avoid the priority inversion problem, based on channels. This solution offers a different concurrency model than the classical one of Java invocations. On the other hand, PERC modifies the Java language introducing two new statements that allow mutual exclusion. In this solution, a task can not use the Java synchronize statement. Only the RTJ-08 solution presents changes in the synchronize semantics to extend it for real-time. A question to consider, related with this mechanism, is whether to use the synchronize statement for communication among threads and tasks. In RT Core, the methods provided for communication with semaphores 1 Since a timeout must be considered as a regular operation by a realtime task, it is not raising an exception. 2 raising a timeout exception. 3 straight-line code, final or static methods with analyzable code, and the following statements: if-then-else, switch, try-catchfinally, break, continue, throw, timed and for-loop with certain conditions.
have different syntax for each API (e.g baseline and core ˆ domains). An original and simple solution is the RT JavaO proposal, which introduces a timeout for communication among threads and tasks. Finally, the RTJ-02 solution presents compliance with the POSIX standard from the coordination and synchronization point of view. And the RTJ-08 solution presents compliance with the standard (non real-time) Java, because coordination and synchronization are made in the same way (e.g by the synchronize statement). This feature makes the RTJ-08 solution particularly interesting.
5. Asynchronous event handling An event is not synchronized with the execution of a particular task, and may be generated by any task or by the hardware. Asynchronous exceptions enable a thread to be asynchronously interrupted by another. From the real-time point of view, this mechanism presents some problems in Java. There is also another general (non real-time) problem: asynchronous exceptions can leave shared data in an inconsistent state. This mechanism has been recently deprecated by Sun. Efficiently dealing with asynchronous events is fundamental to real-time. How studied solutions treat event management are sketched below. RTJ-02. In this proposal, the RealtimeEventGenerator abstract class is the base class for all objects that can generate a RealtimeEvent like asynchronous I/O or timer interrupts. Each RealtimeEvent object can be preallocated to avoid allocation at event time, or can be generated dynamically, it can also specify an event priority. If there are multiple events triggered by the same object, they are queued in order of arrival. These classes can be implemented above RTOS signals or events. RTJ-08. This solution provides two classes: AsyncEvent and AsyncEventHandler to treat events. An AsyncEvent object is like a POSIX signal or a hardware interrupt, and can have a set of handlers associated. An AsyncEventHandler has a SchedulingParameters object associated, which controls its execution. RT Core. Blocking inside an interrupt handler is prohibited. Then, the body of each interrupt handler must be execution-time analyzable4 . Interrupts handlers must be declared as Atomic Synchronized to defer abortion until its execution is completed. 4 In RT Core, execution-time analyzable has the same meaning as in PERC.
PERC. This solution proposes a real-time variant of Java asynchronous exceptions. For instance, multiple exceptions thrown to a PERC task can be queued, and blocked I/O operations and wait() invocations would be interrupted when an asynchronous exception is thrown. The atomic statement allows specifying when certain sequences of code cannot be interrupted, the asynchronous exceptions are deferred.
GVM. A similar, but simpler solution than PERC is given by this solution that provides a primitive that allows supporting the stopping or killing of tasks. This primitive defers the delivery of asynchronous exceptions until a welldefined cancellation point.
Discussion. Two very different solutions to treat events are proposed: based on the model that Java presents for asynchronous exceptions, and based on new classes supporting events. PERC efforts are centralized on how to solve the problems presented by asynchronous exceptions in Java (e.g. how to handle nested asynchronous exceptions). In order to allow deferring an asynchronous exception, PERC presents two new statement (e.g. atomic, timed, and realtime), and imposes several restrictions to the language. A similar solution is given by RT Core that defines the Atomic interface and imposes restriction to task abortion. Questions related to asynchronous events in these solutions, include whether a task may be able to defer asynchronous exceptions, whether an asynchronous exception can be deferred indefinitely, whether a blocking operating system call (e.g. I/O operation) can be interrupted, and whether operating system signals and hardware interrupts can be mapped onto Java asynchronous exceptions. Different from PERC and RT Core, the event models preˆ and GVM are not disented by RTJ-02, RTJ-08, RT JavaO, rectly based on the Java stop() method. Whereas RTJ-02 presents a complex model based on events with priority levels and callbacks for notification, RTJ-08 presents a simple and elegant solution consisting of two classes: a class to support the event functionality and another class supporting the functionality for event handler. The GVM solution does not solve the problems of task termination, but it enables canceling activities without compromising the kernel ˆ is under defintegrity. The solution presented by RT JavaO inition, there is only an event abstract class supporting the timer and interrupt subclasses. General questions to solve are whether a task can suspend and resume other tasks, whether a task can send an event to other tasks, and whether a task can mask some events and accept some others. Moreover, masking interrupts has some problems because it affects the entire machine.
6. Resource management Resource management can be studied from four points of view: the ability to track resource usage (resource accounting), the ability to reclaim the resources of an activity when it terminates (resource reclamation), the ability to assign resources to an activity (resource allocation), and the ability to change the resources assigned to activities (resource negotiation). Resource accounting is influenced by the way in which activities obtain services, and is difficult when there are shared system services. Resource reclamation presents some problems when a task terminates exceptionally. Activities can negotiate dynamically with the real-time executive for resource allocation. A solution to resource management and negotiation has not yet been addressed by the NIST group. However, its recommendation is to negotiate resources via the API. How resource management is treated by studied solutions is given in the following: RTJ-02. In this proposal, resources can be bounded. The ResourceLimits class determines the resource constraints of all tasks (RealtimeThread objects) created within an activity (RealtimeThreadGroup object). When the real-time virtual machine detects that a task exceeds the limits set to its resources, a ResourceOverflowError exception is thrown. RTJ-08. In this solution, prior to starting a task, MemoryParameters must be assigned to it. These parameters are used for both the scheduler (to control admission) and the GC (to satisfy all tasks allocation rates). The scheduler can generate an exception to reject workloads, when a task exceeds a resource limitation, or when a task allocates memory faster than the garbage collection budget allows. PERC. The Activity class offers the methods configure(), negotiate(), reconfigure() and commit(). The executive analyzes availability of resources and determines when to accept a new real-time activity. The ConfigurationManager class provides the analyzeEET() method that gives the expected execution time of a method, and the sizeOf() method that returns the worst case numbers of bytes required to represent an object. GVM. In this solution, each activity is associated with its own heap. Kernel objects, shared classes, and shared data reside in the system heap. Direct sharing among heaps is not allowed, which permits efficient communication. When two activities want to communicate, they must share an object that resides in the system heap.
Discussion. In PERC and RTJ-08, the resources budgets are: CPU time, memory, and memory allocation rate. On the other hand, memory allocation rate is not considered in RTJ-02, because the garbage collection is disabled for realtime activities. GVM further handles network bandwidth, a resource not controlled by RTJ-08, RTJ-02 nor PERC. Network bandwidth is a resource not traditionally treated, but that is very important in Java due to the network nature of this environment. What resources must be considered and how they must be managed are difficult questions that should be treated in the standard real-time extension of Java. To control the CPU time used by an activity, two mechanisms are needed: accounting and preemption. The CPU time consumed by a task must be accurately accounted and when the task exceeds its time limits, it is preempted. With respect to memory, the two issues that must be addressed are how the memory is shared between activities, and how allocation and deallocation are managed. There is a strong relationship between the allocation and accounting schemes, complex allocation management with flexible sharing policies can make reclamation difficult. In order to negotiate resources, the memory in PERC is partitioned among each activity. The use of a separate heap for each activity in GVM, simplifies time and memory accounting, allowing fine grained and exact accounting for resources. Resource management is related with the communication model between activities. The standard JVM supports a direct sharing communication model. This model makes difficult resource reclamation, for example when a task is killed and have shared objects with other tasks. GVM presents an indirect sharing model, objects are shared through a level of indirection or proxy. Hence, this model is less efficient than direct sharing. However when a task is killed, its shared objects are reclaimed whitout problems. When activities have no address space shared, copying is the only possibility. This solution is the most flexible and the most adequate for a distributed real-time extension of Java. Another problem is the establishment and modification of resource reservations and resource limits. PERC presents an interesting solution for both questions, because it supports resource configuration and negotiation, offering both: minimum (pessimistic) and desired (optimistic) resources. Another issue relates to tools to estimate the worst execution time of a task, or the memory requirements of an activity. PERC is the only solution that provides utility methods that are used for analyzing resource requirements of activities. In general, static analysis is used to determine average-case, and performance measures are used to determine worst-case. It is also advisory to use a combination of both, analytical and empirical techniques, to evaluate resource usage and to optimize resource consumption.
7. Dynamic memory management The GC of standard Java is a separate thread that is executed when the system is being detected as idle; once it is started, it must be executed until completion, and can not be stopped or preempted, because this will leave the heap in an inconsistent state. A real-time GC is triggered like a task, and when another task with higher priority arrives, the GC is stopped. High priority real-time tasks cannot tolerate unbounded garbage collection pauses, time taken for executing the GC must be bounded. An overview of solutions that addresses this problem follows.
GVM. Each activity has its own heap, distinct from the heaps of the other activities. The GC works separately in each heap. However, it requires two lists for each heap: a list of exit items and a list of entry items. Another issue, is that each heap is not a continuous memory region. picoJava-I. This microprocessor supports a generational GC with hardware aid. Generational collectors are based on the observation that recently allocated objects have higher probability to become garbage. This improves cache and virtual memory performance because locality characteristics of frequently-reused areas.
PERC. This solution presents a sophisticated real-time GC, that is accurate (non conservative), defragmenting and deterministic. The GC works by dividing its total effort into small bursts. After the GC is preempted by a higher-priority task, it resumes where it left its execution. The method gc() in the Activity class allows to invoke it.
Discussion. PERC provides a bounded GC that works in an incremental way. The PERC GC is an elegant solution for real-time systems, but it is not the most efficient6 . In general, the GC overhead must be quantified, the upper bound pauses defined, the preemption time bounded, and the preemption latency clearly specified. RTJ-08 is the only solution that provides information about the behavior of the GC. It is further important to define a guaranteed deallocation rate, and how this guarantee is given: optimistic or pessimistic. In order to allow a constant time for allocations, RTJ-02, RTJ-08, and RT Core solutions provide a pre-allocate memory pool for real-time objects. Whereas the solution proposed by RTJ-02 is the simplest, i.e. static ˆ gives an intermediate solution between memory, RT JavaO explicit and automatic memory deallocation. Rt Core is a tradeoffs between these two kinds of solutions, making distinction between the garbage collection of real-time and non real-time objects. On the other hand, picoJava-I GC improves the average-case performance, at the expense of the worst-case. Since hard real-time systems are centered around the worst-case, it is not appropriate for this type of systems. How a real-time GC should be scheduled is another important question to be solved. Another open question lies in the definition of multiple heaps or a single one. In the case of multiple heaps, it is interesting to consider whether a heap may be shared by a set of tasks. In addition, a distributed GC is needed to collect data structures that are shared across heaps (e.g. GVM). The RTJ-08 solution introduces the scoped memory concept, that allows binding the lifetime of objects allocated within it, and in this way to collect all objects when the scoped memory is no longer used. This is an original solution that combines preallocated spaces with the GC. Another garbage collection possibility is stack-based allocation, which is desirable because execution time properties are easier to capture than heap allocation. Predictable behavior brings an essential property for real-time systems programs.
5 To make volatile a permanent object, it is needed that the object is not referenced from any real-time task.
6 Typical programs will spend between and of their execution time performing work directly related to garbage collection.
RTJ-02. Tasks execute in a pre-allocated space with the GC deactivated. Thus, the interruption of the GC by these tasks is always safe. The PreallocationContext class has two methods: available() to get the amount of available memory in the area, and replenish(), which may cause a garbage collection to clean up space. RTJ-08. The MemoryArea abstract class supports scoped (objects have a limited lifetime), physical (objects in faster memory) and immortal (objects are not collected) memory. The GarbageCollector class provides methods for getting information about the GC behavior (e.g. getOverhead(), getReclamationRate(), and getPreemtionLatency()). RT Core. This solution has two separate heaps, one for baseline threads, and the other for core tasks. Since tasks and threads may share objects, memory sharing must be supported by the underlying RTOS. The AllocationContext class extends CoreTask and supports the the release() method, which makes all objects allocated within a context eligible by the GC. Every task has associated an AllocationContext object. ˆ Whereas tasks deal only with permanent obRT JavaO. jects (not collected), threads deal with permanent objects and with volatile objects. A permanent object may become garbage collectible through an explicit call to the method makeVolatile() integrated in the Object class5 .
30%
50%
Feature
Task Scheduling
Synchronization Communication
Event Handling
Resource Management
Garbage Collection
Hw Access Solution
Priorities
Deadlines
Java/nonJava
Task/Thread
Internal
External
Budgets
Negotiation
Preemptable
Bounded
RTJ-02
-
A
-
-
-
A
A
A
-
A
-
RTJ-08
A
A
A
-
A
A
A
A
-
A
A
RT Core
A
A
A
-
A
A
A
A
-
A
-
ˆ RT JavaO
M
A
-
M
M
M
M
-
-
A
-
PERC
A
A
M
-
-
A
M
A
A
A
M
CTJ
A
A
-
-
-
-
-
-
-
-
-
RTJT
-
A
A
-
-
-
-
M
-
M
-
GVM
M
A
-
-
-
-
-
-
-
-
-
picoJava-I
A
-
-
-
-
-
-
-
-
A
-
Table 1. Comparison of studied solutions
References
8. Conclusion
Dynamic class loading, garbage collection, and multithreading make Java interesting for real-time embedded system construction. On the other hand, several reasons makes Java not appropriate for this kind of systems: it is slow due to the bytecodes interpretation or to the run-time translation of JIT compiler, it is heterogeneous because the low-level code must be written in C, it is incapable of handling real-time tasks because thread behavior is dependent on the JVM and the operating system, and it is problematic because its garbage collection is not adequate for real-time. In this paper, we have given an overview of proposed extensions to Java so as to support embedded, real-time processing. A comparison of these solutions is summarized in Table 1, where we use A, M, and - to respectively mean that the corresponding issue is addressed in detail, only partly addressed, and not addressed. To evaluate a RTJ extension for embedded real-time systems, we must consider factors that reduce the application size, and factors that increase the performance and the compliance with the standard Java (non real-time). Three important questions to be studied are: i) what packages will be supported by the Java real-time API, ii) what classes must be supported by each new package, and iii) how the garbage collector should be run.
[1] G. Back, P. Tullmann, L. Stoller, W. Hsieh, and J. Lepreau. Java operating systems: Design an implementation. Technical report, Departement of Computer Science, University of Utah, August 1998. http://www.cs.utah.edu/projects/flux. [2] L. Carnahan and M. Ruark. Requirements for real-time extensions for the Java platform. Technical report, RTJWG, September 1999. http://www.nist.gov/rt-java. [3] H. McGhan and M. O’Connor. picoJava: a direct execution engine for Java bytecode. IEEE Computer, 31(2), October 1998. [4] G. Hilderink. A new Java thread model for concurrent programming of real-time systems. Real-Time Magazine, January 1998. pag. 30-35. [5] J Consortium. Draf international J Consortium specification. Technical report, J Cconsortium, September 1999. http://www.j-consortium.org/. [6] K.H. Krause and W. Hartmann. RT JAVA proposal. Technical report, A&D GT 1, 1999. http://www.jconsortium.org/rtjw. [7] A. Miyoshi, H. Tokuda, and T. Kitayama. Implementation and evaluation of real-time Java threads. In Real-Time Systems Symposium. IEEE Computer Society, Decembre 1997. pag. 166-174. [8] K. Nilsen. Adding real-time capabilities to Java. Communications of the ACM, 41(6), June 1998. pag. 49-56. [9] Sun’s Java Community Process Real-Time Expert Group. Proposed Java real time API, v0.2. Technical report, Java Software Division of Sun Microsystems, December 1998. http://www.sdct.itl.nist.gov/ carnahan/real-time/sun/api. [10] The Real-Time for Java Expert Group. Real-time specification for Java, v0.8.1. Technical report, RTJEG, September 1999. http://www.rtj.org.