QUICK START
Sun Java Real-Time System 2.1
  

This guide gets you started quickly with Sun Java™ Real-Time System (Java RTS).

All the technical documentation for Java RTS 2.1 (except this Quick Start Guide) is bundled with the release. However, the most recently updated technical documentation is referenced on the Java RTS 2.1 Technical Documentation web page.

See also the Sun Java Real-Time System FAQ (Frequently Asked Questions) for a comprehensive, though not exhaustive, list of questions and answers about Java RTS.

Introduction

The main characteristic of a real-time application is that the system is subject to real-time constraints. Worst-case response times must be deterministic, in other words, predictable within given limits. The Sun Java Real-Time System guarantees determinism by ensuring that time-critical code is executed at the highest priority, even higher than the garbage collector (GC) if needed.

The first Java Specification Request (JSR) issued by the Java Community ProcessSM (JCP) was JSR 1: the Real-Time Specification for Java (RTSJ). The Sun Java Real-Time System (Java RTS) is Sun's implementation of that specification, including a Real-Time Garbage Collector (RTGC).

We define non-real-time and real-time requirements for an application as follows:

  • A non-real-time application has no time constraint requirements.

  • In a real-time application, response times must be deterministic.

    • In a soft real-time application, missing an occasional deadline can be tolerated.

    • In a hard real-time application, time constraints must always be met.

Real-time does not (necessarily) mean "real fast," and therefore Java RTS is more concerned with determinism than with speed. However, the platform does indeed incorporate many features that improve throughput while still guaranteeing determinism.

Determinism can be expressed in terms of jitter, which is central to measuring the deterministic behavior of a program. Jitter measures the variation in a particular response time for a particular computational scenario of interest within a given executing application. With respect to determinism, an ideal value for jitter would be zero, indicating perfect predictability. More realistically, the aim of real-time processing is to reduce jitter to an acceptable level. Moreover, any jitter that occurs must be bounded, that is, we must guarantee that the jitter remains within known bounds.

Java RTS implements not only the Real-Time Specification for Java (RTSJ), but also the specification for Java™ Platform, Standard Edition (Java SE). Therefore, a program that runs on the Java SE platform will also run on the Java RTS platform, although without real-time behavior.

The easiest way to get off to a quick start with Java RTS is to convert an existing Java SE application to Java RTS.

Follow the steps below to improve the determinism of your application.

Step 1. Check Your Java RTS Installation

We assume that you have already installed Java RTS for your platform according to the instructions in the Java RTS Installation Guide. Check your installation as follows:

  • The Unix shell environment must be configured in order to ensure that the relevant executables (primarily java and javac) and libraries in your Java RTS installation are picked up when referenced by name.

    Check that the environment variable JRTS_HOME is set to the absolute path of your Java RTS installation, and that $JRTS_HOME/bin is at the beginning of the list of paths specified by the PATH environment variable.

  • Ensure that you have configured real-time privileges for Java RTS users, as described in the Installation Guide. If these privileges are not granted, your application can fail with messages such as "You don't have the privilege to use high-resolution timers", or "insufficient effective privileges; temporal behavior is not predictable."

  • Check that the correct java launcher (that is, from your Java RTS installation) is being picked up, by executing the command java -version. The output of the command should include the string Java Real-Time System HotSpot(TM) Client VM.

Step 2. Identify Real-Time Threads

Real-time threads are those which must execute within certain limits, that is, in a predictable, deterministic way. Most applications will have a few real-time threads, while the remaining threads are non-real-time, that is, they do not have rigid temporal constraints. Non-real-time threads are instances of the class java.lang.Thread. Java RTS provides a subclass of java.lang.Thread, called javax.realtime.RealtimeThread (RTT). Instances of this class will exhibit "soft" real-time behavior by default. By properly setting the thread priorities (as explained below), you can cause some real-time threads to exhibit "hard" real-time behavior. You need to identify which threads of your application must be RTTs and instantiate them with the RealtimeThread class.

You also need to make sure that the priorities assigned to threads reflect their importance. In addition to the 10 regular Java priorities, Java RTS features a number of unique real-time priority levels, where this number depends on the host operating system (Solaris OS or Linux). A real-time thread of a lower priority can be preempted in its execution by a real-time thread of a higher priority.

Real-time threads can be non-critical (soft real-time) or critical (hard real-time), and this distinction is determined by the critical priority boundary. Real-time threads whose priority is above the critical boundary are called critical real-time threads, while those below the boundary are called non-critical real-time threads. The default for this boundary is the middle of the real-time range, and is OS-dependent.

To determine the minimum and maximum real-time priorities available, use the methods getMinPriority() and getMaxPriority(), respectively, of the javax.realtime.PriorityScheduler.instance().

In addition to having a higher priority, critical real-time threads benefit from a user-defined amount of memory reserved for their use, as explained in Step "Configure the RTGC for Hard Real-Time."

Define a critical real-time thread if and only if it has a definite time constraint. Otherwise, there could be too much competition among these threads for resources.

For a detailed description of Java RTS thread types and their priorities, see the Java RTS Garbage Collection Guide.

Step 3. Configure the Compilation System

The default compilation scheme for a Java program can break the determinism of a real-time program, because the following activites can occur during time-critical phases of program execution:

  • A Java program runs interpreted until a certain threshold is reached and compilation occurs. This is called Just-In-Time (JIT) compilation. But the compilation causes jitter in the program execution, and this breaks determinism.

  • In addition, classes are lazily initialized, that is, when they are first used, and this is also non-deterministic.

  • Finally, symbol references are resolved on-demand. Since this resolution can occur at any time, determinism is not possible.

Java RTS provides the Initialization-Time-Compilation (ITC) scheme, which solves the problems described above by allowing you to control the following:

  • Methods to be precompiled when their classes are initialized. These methods are specified in the precompile list.
  • Classes to be preinitialized. These classes are specified in the preinit list.
  • Classes to be preloaded. These classes are specified in the preload list.

The Java RTS Compilation Guide contains a detailed description of the compilation modes (schemes) for the various thread types and how to configure them.

If you perform no configuration at all, then the run-time compilation can cause jitter that breaks your application's determinism.

However, for purposes of getting started quickly, you can run your application with special Java RTS command-line parameters that specify the automatic creation of files containing the precompile and preinit lists. (Note that, since reinitialization implies preloading, we will not bother creating a preload list here.)

The precompile and preinit files are cumulative, that is, each time you run the application, more methods and classes can be added to the files. Therefore, you should run the application as many times as necessary to ensure that all the time-critical real-time code has been executed, which ensures that the precompile and preinit lists are complete. You might want to run the application with various arguments or in various conditions in order to ensure code coverage. Once code coverage is complete, your real-time application should not suffer from jitter caused by symbol resolution, class initialization, or execution-time compilation.

You can use the following command as an example of a minimum level of ITC configuration:

java \ -XX:+RTSJBuildCompilationList \ -XX:+RTSJBuildClassInitializationList \ -Drtsj.precompile=nhrt.precompile \ -Drtsj.preinit=itc.preinit \ <application> <arguments>

Here is the explanation of what is happening with the example command above:

  • By default, ITC is enabled for RTTs. This means that, when an RTT executes, the methods in the precompile list are compiled when their classes are initialized, and all other methods are JIT-compiled.

  • With the RTSJBuildCompilationList command-line option, Java RTS automatically generates a file containing a list of the methods that were invoked by RTTs; this is the precompile list. The default file name for the precompile list is nhrt.precompile. This file is cumulative, that is, each time you run the application, more methods can be added to the file.

  • With the RTSJBuildClassInitializationList command-line option, Java RTS automatically generates a file containing a list of the classes that were referenced during the compilation of methods at initialization; this is the preinit list. The default file name for the preinit list is itc.preinit. This file is also cumulative, that is, each time you run the application, more classes can be added to the file.

  • The precompile and preinit lists that Java RTS has generated are used in each run of the same application in order to reduce jitter. The use of these files is specified with the -Drtsj.precompile and -Drtsj.preinit command-line parameters.

  • The first time you run the command, Java RTS generates the initial precompile and preinit files.

    As mentioned above, you should run the application as many times as necessary to ensure code coverage.

  • If you run a different application, remember to remove or rename the precompile and preinit files, as they are cumulative.

Step 4. Configure the RTGC for Hard Real-Time

Java RTS includes a Real-Time Garbage Collector (RTGC). This GC can be tuned in various ways to get the best determinism for any given application. However, to get started, only a minimum amount of configuration is necessary.

The RTGC guarantees determinism to critical real-time threads by reserving memory for these threads. This amount of memory is specified with the command line parameter RTGCCriticalReservedBytes. If free heap memory falls below this amount, the non-critical real-time threads are blocked on memory allocation, waiting for the RTGC to recycle memory. This guarantees that the critical real-time threads, and only the critical real-time threads, will be able to allocate memory from this reserved amount. Therefore, you must specify a value for this reserved amount that will ensure that your critical threads will not fail on memory allocation. On the other hand, if RTGCCriticalReservedBytes is too high, the RTGC will run too often and block non-critical threads. This decreases the throughput.

Another parameter, RTGCCriticalBoundary, specifies the priority boundary between critical real-time and non-critical real-time threads. The default for this boundary is the middle of the real-time range, and is OS-dependent. You can modify this command-line parameter to suit the range of thread priorities in your application. The RTGC must get enough CPU time to recycle memory quickly enough for the needs of the critical threads.

You can leave the other parameters at their default values, but if your application does not exhibit the desired determinism, you can try some basic tuning of the RTGC (see the next step).

See the Java RTS Garbage Collection Guide for a detailed description of how the RTGC works.

Step 5. (Optional) Tune the RTGC for Soft Real-Time

The default values for the RTGC parameters should be sufficient for getting started with Java RTS. Optional advanced tuning is described in detail in the Java RTS Garbage Collection Guide.

Java RTS uses a sophisticated auto-tuning mechanism to determine the optimal conditions under which to start the RTGC or boost its priority to a higher level. At the end of each garbage collection cycle, Java RTS calculates a memory threshold based on previously allocated memory and other factors in order to predict how memory might be allocated during the next cycle. It is best to allow this procedure to run with its default values.

The RTGC is fully concurrent, that is, it can recycle memory without stopping your threads. However, it must get enough CPU time to recycle memory faster than the threads consume it. At the same time, you need to find the balance between throughput and predictability (determinism). If you have sufficient CPU time available, you can try changing the number of parallel RTGC worker threads.

Step 6. Run Your Program

Run your program with, for example, the following command. See the next section for an explanation of PrintGC and LogJitterProneEvents. (See also the example in the step "Configure Compilation System.")

java \
-Drtsj.precompile=<precompile-file-name> \
-Drtsj.preinit=<preinit-file-name> \
-XX:RTGCCriticalReservedBytes=<amount> \
-XX:+PrintGC \
-XX:+LogJitterProneEvents \
<application> <arguments>

Step 7. Verify the System Configuration

Use one or more of the following suggestions to check whether your system was correctly configured for your application to be determinstic:

  • The command-line option PrintGC prints GC information after each GC cycle, and this can help solve simple GC issues. The values that are noted "worst" represent values since VM startup, whereas the "min" and "max" values occurred during the last GC cycle. If the "worst" non-fragmented (that is, available) memory falls to zero, this means that at least one thread was blocked during allocation. If you have critical real-time threads, you should increase the value of RTGCCriticalReservedBytes, that is, the memory reserved for critical real-time threads. In fact, even if the "worst" amount is not zero but is very low, you should increase the reserved bytes for critical threads, for safety's sake. See the Garbage Collection Guide for more details.

  • The command-line option LogJitterProneEvents produces a log file of various events that can cause jitter. See the Java RTS Tools, Tuning, and Troubleshooting Guide for details.

  • For more complex issues, you can use the Thread Scheduling Visualizer (TSV). This tool set includes customizable DTrace scripts to record scheduling events in Java RTS, as well as a visualizer to provide a graphic view of these events. For example, you can use TSV to visualize the activity of the compilation thread and GC thread. See the next step ("Further Reading," subsection "Tools and Troubleshooting") for information about how to obtain TSV.

  • You should use the RTSJ real-time API Clock to perform measurements. It is best not to use other clocks (for example, java.util.Date or java.lang.System.currentTimeMillis). For some of these other clocks, the time base is different, synchronized with the world clock. This synchronization can cause jitter when the world clock is updated.

Step 8. Further Reading of Java RTS Documentation

All of the Java RTS technical documents contain information that will help you continue your successful experience. The latest versions of these documents are available on the Java RTS 2.1 Technical Documentation web page.

Basic Information

Installation Guide - Install the Java RTS virtual machine, the kernel modules, and grant privileges to users.

Release Notes - Check release-specific details.

Compilation Guide - Configure the compilation system for maximum determinism.

Garbage Collection Guide - Configure the Real-Time Garbage Collector for maximum determinism.

Java RTS Command-Line Options - Consult the list of command-line options that are specific to Java RTS.

Advanced Information

Technical Information - Learn even more details for improved programming success.

A Practical Introduction to Achieving Determinism - Play with a set of example programs to see how various parameters can affect determinism.

Tools and Troubleshoting

Java RTS DTrace Provider Guide (Solaris OS only) - Use the special DTrace probes provided for use with Java RTS.

Java RTS Tools, Tuning, and Troubleshooting Guide - Get help with troubleshooting.

The Thread Scheduling Visualizer (TSV) tool and accompanying guide. You can download the TSV tool at the same time you download a Java RTS Evaluation. For your convenience, a link to the TSV guide alone is provided on the Java RTS 2.1 Technical Documentation web page.

 

Feedback

For comments and questions, please contact Java RTS Engineering and Marketing.

 

Copyright © 2008 Sun Microsystems, Inc. All Rights Reserved.