Technical Information
Sun Java Real-Time System 2.0_01
  

This document presents some technical information that can help you to use Sun Java™ Real-Time System (Java RTS) 2.0_01.

Contents

Introduction

Basic Technical Information .....
How to Compile and Execute
Controlling Runtime Jitter
Class Initialization Jitter
Interpreter Jitter
Compilation Jitter
Garbage Collection Jitter
Using Multiprocessors for Optimal Determinism for NHRTs
Clocks
Debugging and Profiling
Monitoring, Management, Troubleshooting

Advanced Technical Information .....
Asynchronous Event Handlers
Release Mechanisms for AEH
Handlers Released by System Threads
Additional Notes for Timers
Order of Timer Firings
Timer Thread Priority
Minimum Interval for Timer Firing
Aperiodic Parameters
Maximum Size of Arrival Queue
Memory Management
Configuring Memory Size
Scoped Memory
Debugging Memory Issues
Memory Allocation Limits
Memory Checks and Standard JDK Libraries
Synchronization
Scheduling
Order of Priority Setting
Aynchronous Transfer of Control
Security
Minimum Period Enforced

Reference Information .....
Troubleshooting Tips

Runtime Parameters

Abbreviations Used in This Document

[Readme File]  [Installation Guide]  [Release Notes]  [Compilation Guide]  [Garbage Collection Guide]  [Java RTS DTrace Provider]  [Practical Introduction to Achieving Determinism]

Introduction

This document presents the technical information in three major sections: basic, advanced, and reference.

Be sure to consult the Java RTS Compilation Guide and the Java RTS Garbage Collection Guide for necessary details in those areas.


How to Compile and Execute

The only additional library required to run Java RTS is rt2.jar, located in the <Java RTS install dir>/SUNWrtjv/jre/lib/ directory.

To compile your program, type the following commands:

$ cd <your program dir>
$ javac -classpath \
  <Java RTS install dir>/SUNWrtjv/jre/lib/rt2.jar \
  <your program>.java

Alternatively, you can type the following commands:

$ cd <your program dir>
$ <Java RTS install dir>/SUNWrtjv/javac \
  <your program>.java

Note: Java RTS 2.0_01 is based on the Java Platform, Standard Edition (Java™ SE) version 5.0 Update 13. Therefore, if you are compiling a Java program using Java SE 6 or later for use with Java RTS 2.0_01, include the argument -target 1.5 on the javac command line.

To run the compiled program, type the following command:

$ <Java RTS install dir>/SUNWrtjv/bin/java \
  -classpath <your program dir> <your program>

See section Runtime Parameters for a list of Java RTS runtime parameters.

[Contents]


Controlling Runtime Jitter

This section provides information on how to reduce jitter during the execution of your application.

Class Initialization Jitter

Class initialization in Java programs occurs on demand when a program executes one of the following operations:

  • Call to a static method
  • Access to a static field
  • Class instantiation

Class initialization implies that some extra code will be executed the first time one of the above operations is carried out for a given class, thereby introducing some jitter at execution time. This problem cannot be avoided from an implementation point of view due to the semantics of the Java Programming Language. Instead, the programmer must anticipate this problem and solve it.

The Initialization Time Compilation (ITC) scheme also implies that code will be compiled on the execution of one of the above operations. This introduces even more non-determinism in class initialization.

See the Compilation Guide for a description of how to specify classes to be preinitialized with the ITC scheme.

Interpreter Jitter

Note that the interpreter might require several executions of each bytecode to reach a steady state, producing jitter the first few times a particular branch is taken. The programmer can reduce the jitter by ensuring that the branches used during the mission-critical phase have been previously executed. A simpler solution, however, is to precompile the methods. This compiled code is already optimized and will not be dynamically rewritten, resulting in a steady state obtained at the end of the class initialization. This should be done at least for the NHRTs.

In addition, the RTGC can more efficiently retrieve the stack traces of compiled methods. Therefore, we recommend compiling most the methods that are called by all time-critical threads, in order to reduce the pause time. For additional information on pause times, see the Garbage Collection Guide.

Compilation Jitter

Java RTS provides mechanisms to avoid the delays due to JIT compilation. These mechanisms include the new ITC compilation mode, as well as new policies for JIT compilation. For additional details, see the Compilation Guide.

Garbage Collection Jitter

Java RTS provides two garbage collection technologies:

With the Serial GC, only NHRTs are deterministic and provide latencies in the low tens of microseconds, provided that you follow the guidelines above concerning class initialization and ITC.

With the RTGC, RTTs can also be deterministic, down to the low hundreds of microseconds. See the Garbage Collection Guide.

[Contents]


Using Multiprocessors for Optimal Determinism for NHRTs

For better temporal behavior on a multiprocessor machine, create a processor set devoted to the exclusive use of Java RTS. The creation of processor sets is described below.

Java RTS additionally allows you to dedicate a different, separate processor set to the exclusive use of the no-heap real-time threads (NHRTs) and the RealtimeThreads (RTTs) of Java RTS. This partition of the available processors ensures the best temporal behavior for these threads, by reducing cache thrashing effects.

To request Java RTS to assign the NHRT threads to an existing dedicated processor set, set the option -XX:RTSJBindNHRTToProcessorSet=<processor_set_id>. The processors assigned to this processor set should all be set no-intr to minimize latency and jitter. If this option is set, calling Runtime.availableProcessors from an NHRT will return the number of processors that are available in the processor set that has been assigned to NHRTs.

A similar option, RTSJBindRTTToProcessorSet, can be used to bind real-time threads to an existing dedicated processor set.

Note that, as a consequence of binding Java RTS to dedicated processor sets, high-priority real-time threads might compete for the processors assigned to the Java RTS processor sets, while other processors not assigned to the Java RTS processor sets might remain idle or might run other, lower-priority, non-real-time processes.

Creating and Assigning Processor Sets

If more than one processor is installed in the target machine, the following configuration procedures can help in obtaining better temporal performance and determinism. (Note that the actual benefits of using processor sets depend on the hardware that is used.)

The Solaris operating system allows a machine's processors to be partitioned into a number of smaller, non-overlapping processor sets. Processors that are assigned to a processor set are reserved for the processes explicitly bound to that processor set. Processes that are not bound to that processor set cannot use those processors.

Note: Shell command lines that are shown with a '#' are meant to be executed while you are logged in as the superuser (root).

A new processor set can be created with the following command:

# /usr/sbin/psrset -c
  created processor set <pset id>

Processors can then be assigned to this new processor set with the following command:

# /usr/sbin/psrset -a <pset id> <cpu id>

where <cpu id> refers to one of the on-line processors displayed by the following command:

# /usr/sbin/psrinfo
<cpu id>     on-line   since mm/dd/yyyy hh:mm:ss
<cpu id>     on-line   since mm/dd/yyyy hh:mm:ss
<cpu id>     on-line   since mm/dd/yyyy hh:mm:ss
<cpu id>     on-line   since mm/dd/yyyy hh:mm:ss

The Java RTS Virtual Machine can then be assigned to run in the new processor set as follows:

# /usr/sbin/psrset -e <pset id> <Java RTS command line>

A processor can also be set to no-intr, meaning that it is sheltered from unbound interrupts. A no-intr processor still executes threads, but it is not interruptible by I/O devices. Note that you cannot set all processors in a machine to no-intr, because at least one processor must remain interruptible by the devices.

Setting at least one processor to no-intr provides better latency and reduced jitter. We thus recommend setting all the processors assigned to the Virtual Machine to no-intr. To set a processor to no-intr, use the following command:

# /usr/sbin/psradm -i <cpu id>

For further information regarding these commands, refer to the related man pages.

[Contents]


Clocks

For the best temporal accuracy, Java RTS requires access to the system's high-resolution clock. On the Solaris Operating System, this clock is accessible only to the superuser and to processes or users that have been granted the proc_clock_highres privilege.

If access to the high-resolution clock is not granted, the virtual machine falls back to the regular, less accurate clock, allowing Java RTS to run without particular privileges. As a consequence, the precision of timer operations will degrade, and will be bounded by the precision of the regular system clock, typically 10 milliseconds.

You can request the virtual machine to use the high-resolution clock and to exit if this resource is not available by adding the -XX:+RTSJForceHighResTimer option to the command line.

Java RTS automatically ensures that a single, consistent time source is used for all the time-related operations. If access to the high-resolution clock is not granted, then the cyclic driver will not be used. Similarly, if the cyclic driver is not installed, then the use of the high-resolution clock is disabled.

Note that you should use the RTSJ time API Clock to perform measurements. It is best not to use other clocks (for example, java.util.Date, java.lang.System.currentTimeMillis, or java.lang.System.nanoTime). For some of these other clocks, the time base is different, synchronized with the world clock. This synchronization looks like jitter when this world clock is updated.

The installation example output in the Installation Guide shows the cyclic driver being installed. The cyclic device driver must be installed on the machine for real-time applications.

On x86/x64 machines, Java RTS uses the high-resolution local APIC (Advanced Programmable Interrupt Controller) timer as the primary time source for timed events such as timer expirations, periodic releases, and deadline monitoring. This ensures that the highest time precision is achieved.

If your system does not feature a local APIC, or if the local APIC is not usable, then the Java RTS virtual machine issues the following warning at startup time:

The cyclic driver's backend does not rely 
on the local APIC timer; using legacy PIT timer

In this case, Java RTS falls back to the legacy PIT (Programmable Interrupt Timer), causing the precision of timed events to be limited to 10 milliseconds by default. This precision can be raised to 1 millisecond by editing the /etc/system file, setting the hires_tick variable to 1, and rebooting your system.

[Contents]


Debugging and Profiling

Java RTS supports the Java Platform Debugger Architecture (JPDA), which includes the following interfaces: the Java Debug Interface, the Java Debug Wire Protocol, and the Java™ Virtual Machine Tool Interface (JVMTI).

Since the Java Virtual Machine Profile Interface is a deprecated interface as of Java SE 5.0, we decided not to support it in Java RTS 2.0. Instead, use the JVMTI.

The NetBeans™ Integrated Development Environment (IDE) implements these interfaces, and we recommend using the NetBeans IDE to debug applications running on Java RTS. This release of Java RTS is compatible with NetBeans 5.5.1.

JPDA provides a comprehensive set of features for debugging an application, at the expense of impairing its temporal behavior during the debugging session. Once the debugger is attached to the Java RTS virtual machine, it is possible to stop, inspect, and resume any type of schedulable that is being executed, that is java.lang.Thread, RealtimeThread, NoHeapRealtimeThread and AsyncEventHandler. It is also possible to debug schedulables executing in scoped memory.

However, once the debugger is attached, the temporal behavior of the application is no longer guaranteed, and there is therefore no need to support the Real-Time Garbage Collector (RTGC). In addition, most debugging operations require the suspension of threads. These suspensions impact all the running threads, including the NoHeapRealtimeThreads and the high-priority RealtimeThreads. Therefore, when debug options are specified on the command line, Java RTS automatically activates the non-real-time mark-and-sweep GC.

[Contents]


Monitoring, Management, Troubleshooting

Java SE 5.0 provides a set of experimental and unsupported tools for monitoring and management, as well as for troubleshooting. The Java RTS team provides these tools "as is" because most of the features work with Java RTS 2.0_01 if you do not use the Real-Time Garbage Collector (RTGC) or no-heap real-time threads (NHRTs).

The design of the RTGC and NHRTs introduced differences between Java RTS and HotSpot, for example, in the memory model, the stack design, and other issues. The Java RTS team is continually improving the architecture of the system in order to be able to fully take advantage of these tools.

The team decided to focus on the tools required for sustaining support: jmap and jstack can be used to extract information from core files.

We also worked on the instrumentation required to debug timing issues. Java RTS 2.0_01 introduces an early access version of a new DTrace probe provider for Java RTS, called jrts. The document Java RTS DTrace Provider contains a detailed description of these probes and how to use them, as well as several sample scripts.

JConsole also works as expected. In addition, Java RTS 2.0 introduced management beans for the real-time garbage collector API, allowing you to dynamically monitor and control certain RTGC elements. See Java RTS Garbage Collection Guide.

The other tools are provided as-is and will be improved in future releases.

Here is further status of the tool investigation work:

  • jinfo and jps should work correctly.
  • jmap works on a core file, but the command-line options -heap, -histo, and -permstat are not yet functional.
  • jstack works on core files. Some private symbols of the JVM are not recognized by jstack but can be viewed with dbx or the Solaris pmap tool.

For related information, see the Monitoring and Management for the Java Platform guide and the Java 2 Platform Standard Edition 5.0 Trouble-Shooting and Diagnostic Guide (PDF).

[Contents]


Asynchronous Event Handlers

This section presents some useful information concerning the Asynchronous Event Handler (AEH) mechanism in Java RTS.

Release Mechanisms for AEH

RTSJ makes a clear distinction between an asynchronous event and handlers that have to be executed when such an event occurs. The asynchronous event is represented by the AsyncEvent class and each instance of this class, and a number of handlers can be associated with the event. Each handler is encapsulated in an instance of the AsyncEventHandler class. The Java RTS implementation has been optimized to minimize the number of threads required to execute AsyncEventHandler instances. This optimization is especially efficient when no handlers are blocking; although blocking handlers are fully supported, they require more resources.

When several handlers are associated with the same event, it is important to understand the release mechanism. When the event is fired, all of its associated handlers are conditionally released for execution. Releases are done by execution eligibility order, but this is not an atomic operation. If some handlers have a priority higher than the schedulable that fired the event, they will preempt it, and the release of following handlers will be delayed until the high priority handlers complete or block. This behavior might add some jitter on the release time of low priority handlers associated with the event.


Handlers Released by System Threads

Handlers related to timers, POSIX signals, and deadline misses are released by system threads that are dedicated to each type of handler. The default value for the priorities of these threads is RTSJMaxPriority, which is a constant equal to one greater than the maximum real-time application priority value. It is possible to change these priorities by setting a value to a command-line option, namely, RTSJHighResTimerThreadPriority, RTSJSignalThreadPriority, or RTSJDeadlineMonitoringThreadPriority. The valid values for the system threads are in the range between the maximum and the minimum real-time application priorities. See the Scheduling section for an explanation of how to determine these maximum and minimum real-time application priority levels.

Caution: If you decrease the priority level of one of the system threads, your real-time application will experience different behavior. For example, if you decrease the priority of the POSIX signal thread, then signal handling can be delayed. Ensure that you can justify changing these values.

[Contents]


Additional Notes for Timers

As mentioned above, Java RTS manages all RTSJ timers through a dedicated system thread. This section provides some information to help you manage the actions of these timers.

Order of Timer Firings

One of the side effects of using a dedicated thread to handle all timers is that timers fire in a serialized fashion. If two timers must be fired at the exact same time, the release of handlers associated with the first handler delays the release of handlers associated with the second timer, even if the handlers of the second timer have a higher priority. Note that the delay corresponds only to the handler release, and not to the execution of the handler code. Therefore, this effect might be noticeable when one timer has a huge number of handlers or when a huge number of timers fire at the same time.

[Contents]

Timer Thread Priority

Timer firings occur more often than deadline misses or POSIX signals. Therefore, it might be important to manage the predictability and the impact of timers by tuning the priority of the timer thread. If a high accuracy is required for RTSJ timers, the timer thread's priority must be the highest of all real-time priorities. If the RTSJ timers are not required to be very accurate, but some other threads of the application must be strongly deterministic, the timer thread's priority can be set to a lower value in order to prevent impacting those critical threads. Add the -XX:RTSJHighResTimerThreadPriority=<priority> option to your command-line to change the timer thread's priority.

See sections Handlers Released by System Threads and Scheduling for important information related to changing Java RTS system thread priorities.

Minimum Interval for Timer Firing

The RTSJ does not define a minimum interval for periodic timers, but a timer firing too often can easily overload a system and prevent the execution of other activities. The Java RTS VM protects itself from this situation by enforcing a minimum value for the interval of periodic timers. If an application tries to create a periodic timer with an interval lower than this limit, or if it tries to set a new interval lower than this limit, it receives an IllegalArgumentException. By default, the minimum interval is set to 500 nanoseconds, but it can be modified with the Java property TimerMinInterval, which specifies the minimum interval expressed in nanoseconds. For example, the minimum interval can be increased to 800 nanoseconds by including -DTimerMinInterval=800 on the VM command line.

[Contents]


Aperiodic Parameters

Release parameters have been included in RTSJ to allow developers to control the way new activities are added to the set of schedulables ready to be executed. By setting an arrival time queue size in an AperiodicParameter instance, it is possible to control the number of pending releases of a schedulable. The choice of an ArrivalTimeQueueOverflow policy helps an application to react when too many releases are pending. However, the default ArrivalTimeQueueOverflow policy is SAVE, meaning that every time a new release arrives, its characteristics are saved until its corresponding execution is done. Under this policy, if a low-priority schedulable is released many times but is prevented from running because another high priority schedulable is running, the memory required to store all the characteristics of its releases will continually increase and might completely fill the system memory, causing abnormal behavior. For this reason, it is advisable to change the ArrivalTimeQueue policy of schedulables that might be released many times and that can be prevented from running for a long time.


Maximum Size of Arrival Queue

Aperiodic schedulable objects are associated with an arrival time queue controlled by a parameter object instance of AperiodicParameters. The size of an arrival queue is determined by the value returned by the getInitialArrivalTimeQueueLength() method of the parameter object when the aperiodic schedulable object is created. The value returned by this method can be modified using the setInitialArrivalTimeQueueLength() method.

To prevent the formation of huge arrival queues, which implies huge allocations, the method setInitialArrivalTimeQueueLength() will not accept arguments greater than the value of the Java property ArrivalQueueMaxSize. If the method setInitialArrivalTimeQueueLength() refuses a new size because its value is greater than ArrivalQueueMaxSize, it throws an IllegalArgumentException(). The default value of ArrivalQueueMaxSize is 16384, but it can be modified. For example, the value can be increased to 32768 by including -DArrivalQueueMaxSize=32768 on the VM command line.

[Contents]


Memory Management

This section presents some help with memory management in Java RTS.

Configuring Memory Size

The total memory used for immortal and scoped areas must be configured when starting the JVM. The default values are 32MB and 16MB respectively, and can be modified using the -XX:ImmortalSize=value and -XX:ScopedSize=value options. The VM performs some internal rounding of these total sizes and of the size of each scoped memory area.

To see the memory layout, launch the VM with the -XX:+RTSJShowHeapLayout option.

Scoped Memory

The RTSJ defines ScopedMemory objects to represent alternative memory allocation contexts that are not subject to garbage collection. These are created using concrete subclasses such as LTMemory and VTMemory. The memory that these objects represent is known as the backing-store and is distinct from the object itself. The backing-store is managed by the virtual machine and is not obtained from the allocation context that contains the ScopedMemory instance, or any other memory area directly accessible to Java code.

As defined by the RTSJ, "this backing-store behaves effectively as if it were allocated when the associated scoped memory object is constructed and freed at that scoped memory object's finalization".

The detailed management of the backing-store memory is implementation-dependent, and in Java RTS there can be a delay between the time an area of backing-store is released and the time at which it is available to be used with a new ScopedMemory object. As always with dynamic allocation requests, if a program needs to guarantee that allocation of the ScopedMemory instance and its backing-store cannot fail when it is needed, then that ScopedMemory instance should be created during the initial start-up phase of the application.

The VTMemory and LTMemory classes can be constructed with a requested initial size and maximum size for the backing-store. Java RTS always allocates the maximum size requested for the backing-store upon object construction, to achieve better predictability and determinism and to guarantee the availability of the maximum requested memory. This guarantee is not required by the RTSJ but is provided by Java RTS.

Debugging Memory Issues

Programs that fail because of access checks or assignment checks are particularly hard to debug. Such situations are further complicated when an exception is replaced by a ThrowBoundaryError when it tries to escape its scope. The following options can be useful in these conditions:

  • -XX:+RTSJTraceAccessChecks
  • -XX:+VMStackTraceAtRTSJException
  • -XX:+RTSJIgnoreThrowBoundaryError (see caution note below)

Caution: If you activate the RTSJIgnoreThrowBoundaryError flag, do so only temporarily to obtain information that is hidden because of the replacement of an exception by a ThrowBoundaryError. Activation of this flag might lead to core dumps or other undefined behavior since the concerned object might be deleted while it is still in use. Always disable this option before making a bug report.

Memory Allocation Limits

Java RTS supports only the mandatory memory allocation limits in a MemoryParameters instance, as defined by the RTSJ. The optional parameters (allocation rates) are not enforced.

[Contents]


Memory Checks and Standard JDK Libraries

Under the RTSJ memory model, a legacy Java method might throw new exceptions when writing or reading an object. Hence, some legacy code, including the standard JDK libraries, might result in MemoryAccessError or IllegalAssignmentException exceptions being thrown.

It is important to note that this never happens for a regular java.lang.Thread, which can safely use legacy code and standard Java libraries. Such threads are unaffected because an assignment check fails only if the written object is in a scoped memory area, and an access check is performed only if the current thread is an NHRT. Note that for this reason, legacy code will also continue to work with RealtimeThreads as long as scoped memory is not used. Library calls, however, might fail for NoHeapRealtimeThreads or for RealtimeThreads running inside a scoped memory area, as RTSJ does not define the API set that must be supported in these two cases.

Rewriting a method so that it does not cause a memory exception when used by NHRTs or from scoped memory might result in performance loss, because additional checks must be performed, or optimization such as caching must be disabled. Note also that the design of most of the libraries is based on the assumption that, thanks to the GC, dynamic allocation is inexpensive and harmless. However, dynamic allocation can lead to memory leaks in ImmortalMemory or increase the size required for scoped memory areas. Whenever possible, you should try to delegate the standard library calls from NHRTs to RealtimeThreads, and perform these calls in the Heap memory area.

In any case, if the determinism provided by the Real-Time Garbage Collector (RTGC) is sufficient, then the safest solution is not using NHRTs and scoped memory.

[Contents]


Synchronization

The HotSpot virtual machine handles object locking in a very efficient manner. A locking operation can be performed in compiled code in a few CPU cycles as long as there is no contention. Contended monitors are more expensive because VM calls have to be performed. As a result, considerable jitter might appear once contention happens for a given monitor. If necessary, this jitter can be avoided by explicitly calling MonitorControl.setMonitorControl(obj,PriorityInheritance.instance()). This forces all future locking operations on the object to use the worst-case path.

The Priority Ceiling Emulation Protocol (PCEP) is an optional feature of RTSJ, and is not supported by Java RTS, mostly for reasons of efficiency.

In order to avoid being subject to GC-induced jitter, an NHRT should never lock an object that can potentially be locked by a non-NHRT thread. Note also that such a lock can impact other real-time threads as well, since the owner of the lock could be boosted to the priority of the blocked NHRT. This might even cause the priority of the garbage collector to be boosted as well. In order to anticipate these issues, carefully check the code executed by the NHRTs and pay special attention to the synchronized statements. This is less critical with the RTGC, since the worst-case pause time would be in the hundreds of microseconds.

[Contents]


Scheduling

In addition to the 10 regular Java priorities, Java RTS features 59 unique real-time priority levels. The minimum and maximum priorities are returned by methods in javax.realtime.PriorityScheduler.instance(). These methods are getMinPriority() and getMaxPriority(), respectively.

In the original version 1.0 of the RTSJ specification, the javax.realtime.PriorityScheduler class provided two fields, MIN_PRIORITY and MAX_PRIORITY, to describe the range of supported real-time priorities. The version 1.0.1 of the RTSJ specification has later deprecated these fields. Now, the minimum and the maximum real-time priorities must be obtained by invoking getMinPriority() and getMaxPriority() respectively.

Caution: Since the above two deprecated fields are defined as static and final, they are inlined by Java compilers. Because different Real-Time Java Virtual Machines can implement different priority mappings, inlined values might be meaningless for different VMs. The use of those deprecated fields produces VM-dependent real-time class files and thus might cause undefined temporal behavior on other VMs than Java RTS.

Threads running at a regular Java priority level are scheduled according to a timesharing policy. This policy provides a fair allocation of processor resources among threads. The time-sharing policy is intended to provide good response time to interactive threads and good throughput to processor-bound threads, but not to provide any temporal guarantee. In contrast, threads running at a real-time priority level are scheduled according to a real-time, fixed-priority preemptive policy. Threads scheduled according to this policy are granted the highest range of scheduling priorities on the system.

The regular Java threads are restricted to the regular Java priority range, while the real-time threads can only be assigned real-time priority levels. However, keep in mind that, due to priority inheritance, a regular Java thread can be boosted to a real-time priority level if it holds a lock claimed by a real-time thread. Code executed by a non-real-time thread sharing a lock with high-priority real-time threads must consequently be written carefully.

Caution: Nothing prevents runaway threads running at real-time priority levels from effectively saturating the processor(s), possibly causing the machine to become unresponsive. In this case, the machine might have to be rebooted, either manually or through the service processor or remote management console, if available.


Order of Priority Setting

Note that PriorityParameters.setPriority(priority) is not atomic. If a thread increases the priority value of a PeriodicParameters shared by several other threads, it can be preempted by the first thread that has its new priority set, delaying the priority update of other threads sharing the same PeriodicParameters. In some cases, this might cause priority inversions. The workaround is to ensure that the priority of the thread invoking PriorityParameters.setPriority(newpriority) is greater than or equal to the value of the new priority.

[Contents]


Asynchronous Transfer of Control

Asynchronous Transfer of Control, or ATC, is a powerful mechanism that safely extends Thread.stop().

ATC users should keep in mind the following rules:

  • ATC has been defined at the Java-language level, rather than at the byte-code level. For performance reasons, Java RTS relies on the fact that locks are always properly nested in a Java frame. Hence, ATC might not work as expected if locks are not properly nested in a frame corresponding to an interruptible method. Improperly nested locks should never happen if the byte code has been generated with a compliant Java compiler. However, if you plan to use a code obfuscator, please check with your vendor before using such a tool on RTSJ code.
  • Do not forget that finally statements cannot be executed in asynchronously-interruptible methods. A finally statement is transformed into statements equivalent to catch(Throwable e) { ... code ... ; throw e; }. Unfortunately, when an ATC is delivered, the code statements might not be executed, because they are not in a deferred section.
  • Do not forget to call aie.clear() in the catch handler. This is the main difference between the AsynchronouslyInterruptedException delivered by ATC and a regular exception. An instance of AIE delivered by aie.fire() or Thread.interrupt() is re-thrown as soon as the thread exits from the deferred section in which the handler was found, unless it has been explicitly cleared.
  • Note that calling throw(new AsynchronouslyInterruptedException()) uses the regular exception delivery mechanism rather than the ATC mechanism. This exception is delivered synchronously and need not be cleared.
  • As a special case of uncleared AIE, you should never include a loop in a deferred section that contains a generic handler (catch (Exception or catch (Throwable). If this handler catches an AIE, this exception will be re-thrown as soon as the thread reenters the non-deferred section inside the loop.
  • In your design, implement interruptions through aie.doInterruptible(logic) and aie.fire() rather than through Thread.interrupt(). This allows you to interrupt the right logic in case of nested interruptible logic. Thread.interrupt() should be used only to safely terminate a thread.

[Contents]


Security

Java RTS 2.0_01 provides a secure environment on a par with Java SE 5.0 Update 13. For Java RTS 2.0_01 deployments that are not "closed," the use of trusted third-party applets and applications helps ensure the highest security.

Changes in Acquisition of Access Control Context

In Java RTS 2.0, when a no-heap real-time thread was created, it acquired its inherited access control context in the normal manner. However, when a no-heap real-time thread created another thread, the inherited access control context of the new thread would be set to null. This was done to avoid having the no-heap real-time thread encounter a heap-allocated AccessControlContext instance. The net effect of this is that the created thread, due to the missing inherited access control context, might have a higher level of permissions than it would otherwise have had.

In Java RTS 2.0 update 1, this behavior has been modified as follows. When a no-heap real-time thread is created, it is given a null inherited access control context. This ensures that the no-heap real-time thread object will not hold a reference to a heap allocated AccessControlContext instance. However, when the no-heap real-time thread creates another thread, that thread (unless also a no-heap real-time thread) will acquire an inherited access control context in the normal manner, based (in part) on the code in the current execution stack.

This change implies that the no-heap real-time thread might have permissions it would otherwise not have had, but a no-heap real-time thread (like a real-time thread) is already considered a privileged execution context that should only be created by, and execute, trusted code.

Further, it is a simple matter to remove permissions from the no-heap real-time thread, or from any thread created by the no-heap real-time thread, by using a custom security policy that does not grant the permission to the codebase from which the code for the thread comes, or via which the new thread is created. For example, suppose all classes in the application classpath form a codebase that has all permissions granted, and you wanted to restrict the permissions of a plain java.lang.Thread when created by a specific no-heap real-time thread. You could define the following factory class to be used by the no-heap real-time thread to do the Thread creation:

public class Restricted {
   public static Thread newThread(Runnable r) {
       return new Thread(r);
   }
} 
Then you place this class in a separate codebase, which does not have the permissions of interest, in the custom security policy used. When the no-heap real-time thread calls Restricted.newThread to create the new thread, the inherited access control context of the new thread will contain the restrictions applied to the Restricted class. When the new thread executes, its current access control context will also contain those restrictions and the thread will be unable to perform actions that require the permissions that have been denied.

For more details on access control contexts, security policies and permissions see the Java Platform Security Guide.

For backward compatibility with Java RTS 2.0, two system properties can be defined to restore the old behavior:

  • rtsj.security.setNHRTInheritedACC

    If this property is defined, then at construction, a no-heap real-time thread will acquire an inherited access control context using the normal mechanism, rather than setting it to null. Note that if this inherited access control context is heap allocated, then the no-heap real-time thread might encounter a MemoryAccessError if it attempts a security-checked action.

  • rtsj.security.IgnoreInheritedACCFromNHRT

    If this property is defined, then at construction, a thread created by a no-heap real-time thread will have its inherited access control context set to null.

[Contents]


Minimum Period Enforced

Java RTS enforces a minimum period for periodic release parameters that are associated with a real-time thread. Periods shorter than the minimum value are accepted but are silently raised to that minimum value to try to avoid system hangs. No error, warning, or exception is currently reported.

This minimum period value is set by default to 50 microseconds. This value can be changed by editing the /platform/<arch>/kernel/drv/cyclic.conf file, setting the cyclic_min_interval variable to the appropriate value (expressed in nanoseconds), and rebooting your system.

Note that lowering the value of this minimum period can potentially cause your system to hang, if an application specifies an unreasonably short period.

[Contents]


Troubleshooting Tips

In addition to the monitoring, management, and debugging information provided in other sections of this document, this section provides tips for solving some specific issues related to using Java RTS.

Throughput Loss Possibly Due to Cross Calls

When a compiled method calls an interpreted method, or vice-versa, this is known as a "cross call." Such calls might produce a significant (and unexpected) throughput penalty.

Within HotSpot, methods that call each other are compiled at approximately the same time, resulting in optimal performance. With ITC, users must be more careful.

Unlike other flavors of threads, NoHeapRealtimeThread threads (NHRTs) cannot be subjected to JIT compilation. Therefore, if some methods executed by NHRTs are not in the user-provided ITC compilation list, both determinism and throughput might be compromised. For example, a given list could produce a set of methods whose execution is slower than the same set of entirely interpreted methods.

For other threads, JIT compilation (if not disabled) will take care of this issue in the long term, but the application will suffer from jitter and throughput problems in the initialization phase if the ITC list leads to too many cross calls.

For detailed information about JIT, ITC, and the ITC compilation list, see the Compilation Guide .

Balancing Determinism and Debugging

The use of some of the monitoring tools or supporting library calls in Java RTS can lead to determinism issues. For instance, Java RTS must suspend the application to take a snapshot of the thread states and look for deadlocks. By default, determinism is considered to be more important than obtaining all the information that HotSpot is able to provide. However, during application development you might be more interested in the debugging functionalities than in determinism.

Therefore, Java RTS provides mechanisms to select between a very deterministic deployment mode and a less deterministic development or debugging mode.

The behavior can be changed dynamically with a monitoring bean: JRTSDebugMXBean.

This currently impacts only the stack trace information and the thread state snapshots. Both are controlled by a single parameter that can also be changed with a command-line option (turned on by default): -XX:-RTSJDisableAtomicThreadDump.

[Contents]


Runtime Parameters

These tables describe the -XX runtime parameters that are related to Java RTS. See Java HotSpot VM Options for a list of all the -XX options and how to use them.

See also the Java RTS Compilation Guide and the Java RTS Garbage Collection Guide for runtime parameters specific to those areas.

The -XX:+flag syntax sets a boolean flag to true, and -XX:-flag sets it to false. For parameters that take values, the syntax is -XX:param=value.

These parameters are intended either for a production environment or a development environment. Development parameters are available only to the debug version of the virtual machine (that is, java_g). Note that development parameters might not be maintained from one release to another. Note also that certain development parameters might produce I/O that can change the temporal behavior of the VM.

Caution: Options that are specified with "-XX" are not stable and are not recommended for casual use. These options are subject to change without notice.

Table: Memory-Related Parameters

Parameter

Default

Env

Description

ImmortalSize

32M

prod

The amount of immortal memory to allocate.

ScopedSize

16M

prod

The total amount of memory for all scoped memory allocations.

RTSJTraceScopeStacks

false

dev

Enable tracing of scope stacks. Stacks are printed on changes.


Table: Thread-Related Parameters

Parameter

Default

Env

Description

RTSJTraceThreading

false

dev

Trace (print) real-time thread scheduling events, such as thread start and death, priority modification or boost, blocking on lock, waiting.

RTSJTraceThreadBinding

false

prod

Trace the binding of threads to processors.

RTSJBindNHRTToProcessorSet

N/A

prod

Bind NHRTs to the processor set whose ID is specified by the value of the parameter.

RTSJBindRTTToProcessorSet

N/A

prod

Bind RTTs to the processor set whose ID is specified by the value of the parameter.

RTSJForceCyclic

(Used only with non-real-time applications.)

Use driver if available; otherwise, fall back to built-in support.

prod

Force or prevent usage of the cyclic device driver when running non-real-time applications.

  • Default (no value specified): Use driver if available; otherwise, fall back to built-in support.

  • Value = true: Use driver if available; otherwise, exit.

  • Value = false: Do not use driver. Use built-in support instead.

VMStackTraceAtRTSJException

false

dev

Print stack trace information for an RTSJ-specific exception.


Table: Access-Related and Assignment Check-Related Parameters

Parameter

Default

Env

Description

RTSJTraceAccessChecks

false

dev

Enable tracing of access checks. Illegal accesses are reported. (Used only in interpreted mode.)

RTSJTraceAssignmentChecks

false

dev

Enable tracing of assignment checks. Illegal assignments are reported. (Used only in interpreted mode.)

RTSJIgnoreThrowBoundaryError

false

dev

Let an exception escape its scope instead of replacing it. This allows the developer to dump the stack trace. (See Caution note below.)

Caution: If you activate the RTSJIgnoreThrowBoundaryError flag, do so only temporarily to obtain information that is hidden because of the replacement of an exception by a ThrowBoundaryError. Activation of this flag might lead to core dumps or other undefined behavior since the concerned object might be deleted while it is still in use. Always disable this option before making a bug report.

Table: Asynchrony-Related Parameters

Parameter

Default

Env

Description

RTSJSignalThreadPriority

RTSJMaxPriority

prod

Priority of the thread handling POSIX signals.

See Handlers Released by System Threads.

RTSJForceHighResTimer

Use high-resolution timers if available; otherwise, fall back to regular, low-resolution timers.

prod

Force usage of the high-resolution timers.

  • Default (no value specified): Use high-res timers if available; otherwise, fall back to low-res timers.

  • Value = true: Use high-res timers if user has privileges; otherwise, exit.

  • Value = false: Do not use high-res timers. Use low-res timers instead.

RTSJHighResTimerThreadPriority

RTSJMaxPriority

prod

Priority of the thread releasing handlers associated with timers.

See Handlers Released by System Threads.

RTSJDeadlineMonitoringThreadPriority

RTSJMaxPriority

prod

Priority of the system thread responsible for deadline monitoring.

See Handlers Released by System Threads.


Table: Compiler-Related and Interpreter-Related Parameters

.

Parameter

Default

Env

Description

RTSJTraceNHRTInterpreted

false

prod

Trace bytecodes executed by an NHRT.

RTSJTraceInterpreterEntry

false

prod

Restrict bytecode tracing to print only the name of methods called (to be used in conjunction with RTSJTraceNHRTInterpreted or TraceBytecodes).

[Contents]


Abbreviations Used in This Document

AEH - Asynchronous Event Handler

ATC - Asynchronous Transfer of Control

GC - Garbage Collector

ITC - Initialization Time Compilation

Java RTS - Sun Java™ Real-Time System

JIT - Just In Time compilation

JLT - an instance of the java.lang.Thread class.

NHRT - No Heap Realtime Thread; an instance of the NoHeapRealtimeThread class.

RTGC - Real-Time Garbage Collector

RTT - Realtime Thread; an instance of the RealtimeThread class.

RTSJ - Real-time Specification for Java

[Contents]


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