Tutorial: Guidelines for developing real-time and safety-critical embedded Java software - Part 4
In Part 2: 14 basic rules for use of the Real Time Specification for Java in safety critical real time tasks in embedded systems.
A good working definition of safety-critical Java code is that it is
software that must be certified according to DO-178B or equivalent
guidelines. Certification guidelines impose strict limits on software
practices, including peer review, traceability analysis, and software
testing.
More specifically safety-critical Java uses a subset of the full
hard real-time mission-critical capabilities, covered in the first
three parts in this series. While it supports the notion of scoped
memory, it hides the RTSJ APIs that manipulate memory scopes. Instead,
safety-critical Java programmers describe their intentions with respect
to use of scoped memory by using annotations which can be statically
analyzed and enforced at compile time.
Following are 14 rules to
follow when doing Java development in safety
critical applications:
Rule 1. Except where indicated to
the contrary, use hard real-time programming guidelines
In general, all of the hard real-time guidelines are appropriate for
safety-critical development, except that certain practices acceptable
for hard real-time mission-critical development should be avoided with
safety-critical software (as indicated in the subsequent rules).
Rule 2. Use only 28 priority levels
for NoHeapRealtimeThread
The official RTSJ specification states that a compliant implementation
must provide at least 28 priorities, but may support many more. For
safety-critical development, application software should limit its use
of priorities to the range from 1 though 28. Vendors can readily
support this priority range as a standard safety-critical platform.
Rule 3. Use only instances of
COMPLIANT-mode NoHeapRealtimeThread
In safety-critical systems, the sharing of data and control between
native code and safety-critical Java code should be avoided if
possible. This is because native code cannot be scrutinized by the
safety-critical byte-code verifier.
Rule 4. Prohibit use of
@OmitSubscriptChecking
annotation
In safety-critical code, turning off subscript checking is strongly
discouraged, even though static analysis of the program presumably has
proven that the program will not attempt to access invalid array
elements. In safety-critical systems, the key benefit of subscript
checking is to prevent an error in one component from propagating to
other components.
Rule 5. Prohibit use of @OmitScopeChecking annotation
In safety-critical code, turning off assignment scope checking in
methods that permit @AllowCheckedScopedLinks
is strongly discouraged, even though careful inspection of the program
may have determined that the program will not attempt to make
assignments that would violate nested scoping rules.
Rule 6. Prohibit invocation of
methods declared with the @AllowCheckedScopedLinks
annotation
This annotation is designed to allow programmers to use practices that
cannot be certified safe by automatic static theorem provers. Thus,
there is a risk that any software making use of this annotation will
abort with a run-time exception. Allow this practice only in
safety-critical systems for which developers are able to provide
absolute proof that run-time exceptions will not be thrown.
Rule 7. Require all code to be @StaticAnalyzable
In hard real-time mission-critical code, the use of the @StaticAnalyzable annotation is
entirely optional. In safety-critical code, we require all components
to have this annotation, and for all relevant modes of analysis to have
a true value for the enforce_time_analysis,
enforce_memory_analysis, and enforce_non_blocking attributes.
Rule 8. Require all classes with
Synchronized virtual methods to inherit PCP or Atomic
The safety-critical profile does not allow the use of priority
inheritance locking.
Rule 9. Require all classes with
Synchronized static methods to inherit StaticPCP or StaticAtomic
The safety-critical profile does not allow the use of priority
inheritance locking.
Rule 10. Prohibit dynamic class
loading
While dynamic class loading may be supported in the hard real-time
mission-critical domain, it should be strictly avoided in
safety-critical software.
Rule 11. Prohibit use of blocking
libraries
Because of difficulties analyzing blocking interaction times when
software components contend for shared resources, all services that
might block are forbidden in safety-critical code. Specifically, it is
recommended to avoid use of the following APIs in safety-critical
application software:
java.lang.Object.wait()
java.lang.Object.wait(long)
java.lang.Object.wait(long, int)
javax.realtime.util.sc.NoHeapRealtimeThread.join()
javax.realtime.util.sc.NoHeapRealtimeThread.join(long)
javax.realtime.util.sc.NoHeapRealtimeThread.join(long,
int)
javax.realtime.util.sc.NoHeapRealtimeThread.sleep(long)
javax.realtime.util.sc.NoHeapRealtimeThread.sleep(long,
int)
javax.realtime.util.mc.ThreadStack.join()
javax.realtime.util.mc.CountingSemaphore.P()
javax.realtime.util.mc.SignalingSemaphore.P()
javax.realtime.util.mc.Mutex.enter()
Rule 12. Prohibit use of PriorityInheritance MonitorControl
policy
Priority inheritance is more difficult to certify, more complicated to
implement, and less efficient than priority ceiling emulation. Also,
the implementation of priority inheritance introduces synchronization
overhead delays that are proportional to the complexity of the
application, rather than a function only of the system configuration.
Analyzing these delays is particularly difficult. For all of these
reasons, we prohibit its use in safety-critical software systems.
Rule 13. Do not share
safety-critical objects with a traditional Java virtual machine
Combining safety-critical code with traditional Java code using the @TraditionalJavaMethod and @TraditionalJavaShared conventions
compromises the integrity of the safety-certification artifacts. This
practice is therefore strictly forbidden.
Rule 14. Use development tools to
enforce consistency with safety-critical guidelines
To enforce that programmers make proper use of the safety-critical
subset and that all code is consistent with the intent of the hard
real-time programming annotations described in this section, use
special byte-code verification tools that help assure reliable and
efficient implementation of programmer intent.
Kelvin
Nilsen, Ph.D. is chief technology officer at Aonix North America
To read Part 1 go to Alternatives to garbage collection
To read Part 2 go to Soft Real-Time
Development Guidelines
To read Part 3 go to Hard Real-Time
Development Guidelines
References:
[1] Guidelines for Scalable Java Development of Real-Time Systems,
available at http://research.aonix.com/jsc/rtjava.guidelines.3-28-06.pdf