Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX

By submitting your information, you agree that devx.com may send you DevX offers via email, phone and text message, as well as email offers about other products and services that DevX believes may be of interest to you. DevX will process your information in accordance with the Quinstreet Privacy Policy.


Go Inside the Java Real-Time System : Page 2

Real-time Java is about more than applications that need to be fast. Find out what real-time requirements actually are and get an in-depth look at what Sun Microsystem's real-time Java can do for you.




Application Security Testing: An Integral Part of DevOps

Java RTS Application Development
You can begin your journey into real-time development today with any Java application, assuming you have access to Java RTS (available from vendors that support the RTSJ specification, such as Sun or IBM). Simply change all instances of Thread in your code to RealtimeThread. Once you do this, you're done. Your application will now achieve soft real-time behavior within those threads. To build a robust deterministic real-time system you will want to go further, however this is an excellent start that will prove ample for many real-time applications.

To use the RealtimeThread class in your system, you can either extend it directly, or implement Runnable and assign it to a real-time thread. The first example, shown in Listing 1, extends RealtimeThread and is straightforward. In this code, the main deviation from normal thread programming is the need to specify the thread's priority via the PriorityParameters class, and the thread's period (how often it wakes up to do work) via the PeriodicParameters class. These are passed into the RealtimeThread class constructor. Also note that instead of calling Thread.sleep in the thread's run method, a call is made to RealtimeThread.waitForNextPeriod. This call uses a high-resolution timer and the internal real-time facilities of Java RTS, to ensure temporal behavior and sleep for the period specified in the thread's constructor.

If you choose not to extend Thread or RealtimeThread, but prefer to implement Runnable instead, you can do that also. The code is similar; you instantiate the Runnable class as you normally would, and then create a RealtimeThread with the same parameters as before, plus the Runnable class object, as shown below.

// Instantiage the Runnable class MyRTClass2 runnableObj = new MyRTClass2(); // Create the RealtimeThread thread and supporting parameters PriorityParameters sched = new PriorityParameters( PriorityScheduler.instance().getMaxPriority()); PeriodicParameters period = new PeriodicParameters(new RelativeTime(1,0)); RealtimeThread rtt = new RealtimeThread( sched, period, null,null,null, runnableObj );

Your Runnable class will likely be devoid of any real-time specific code. However, it's important to remember to call RealtimeThread.waitForNextPeriod instead of sleep, or you will not get real-time behavior. There are other facilities of Java RTS that you may choose to use, such as scoped memory, immortal memory, and NoHeapRealtimeThread. Let's take a look at these now.

Scoped Memory; Immortal Memory; and NoHeapRealtimeThread
Scoped memory is represented by an object that you instantiate in your code and then use to create other objects within. The threads that execute within that scoped memory space govern the lifetime of those objects. When all threads exit the scoped memory space, all of the objects within it are de-allocated immediately.

Scoped memory areas can be nested, with a parent-child relationship, and behave like a stack. For instance, if a running real-time thread enters a scope, the scope it was in previously becomes the parent of the newly entered scope. When the thread leaves that scope, it will return to the original (parent) scope. There are some rules for scopes due to the need to maintain the proper parenting relationship. For instance, Java threads cannot be created within a scope; they must be created on the heap or in immortal memory, and can then enter a scoped memory area to execute. Let's take a look at how this works.

In Listing 2, MyRTClass3 extends RealtimeThread and creates a scoped memory region of type LTMemory. This type of memory region is guaranteed to have constant, linear time for allocations that do not require the region to expand beyond its initial size. The class, Worker, is created on the heap and is provided to the scoped memory region via the method LTMemory.enter. The Worker object will then execute in its own thread within the scoped memory region. All objects created within that region will be freed when the thread exits.

Immortal memory is quite different from scoped or heap memory, as objects created within are not subject to garbage collection. Therefore, real-time applications should be judicious in their usage of this special memory region, as it represents a finite resource. Table 1 illustrates the complete set of memory access rules for all memory region types in Java RTS:

Table 1—The Java RTS Memory Access Rules

Stored in: Reference to heap Reference to immortal Reference to scoped
Heap Yes Yes No
Immortal Yes Yes No
Scoped Yes Yes Only the same or an outer scope
Local Variable Yes Yes Yes

The table shows that objects in the heap or in a scoped memory region can reference objects in immortal memory. However, scoped memory cannot be referenced by any memory region other than the scope itself or an outer scope (the parent scope, the parent's parent, and so on).

There are different ways to use immortal memory:

  • You can directly create objects within it from any real-time thread:

    // Create an immortal object directly try{ Object inImmortal = ImmortalMemory.instance().newInstance(Object.class); } catch (IllegalAccessException ae) { ae.printStackTrace(); } catch (InstantiationException ie) { ie.printStackTrace(); }

  • You can provide a Runnable class to enter the immortal memory region:

    import javax.realtime.*; public class MyRTClass4 extends RealtimeThread { Object immortalObj; public void run(){ // Enter immortal memory and create an immortal object ImmortalMemory.instance().enter( new Runnable() { public void run(){ MyRTClass4.this.immortalObj = new Object(); } ); } // ... }

  • You can explicitly create a RealtimeThread with the immortal memory region provided as a constructor parameter:

    // Instantiage the Runnable class MyRTClass runnableObj = new MyRTClass(); // Create the RealtimeThread thread and supporting parameters PriorityParameters sched = new PriorityParameters( PriorityScheduler.instance().getMaxPriority()); PeriodicParameters period = new PeriodicParameters(new RelativeTime(1,0)); RealtimeThread rtt = new RealtimeThread( sched, period, null, ImmortalMemory.instance(), null, runnableObj );

Regardless of how you choose to use it, immortal memory represents a paradigm shift in object allocation and usage in Java. This pattern may seem awkward at first, but it provides a safe memory region that is guaranteed to be free of garbage collection pauses for the life of your application. This is a crucial component of Java RTS that enables hard real-time behavior in applications that require it. Now let's look again at the sample real-time application introduced earlier in the article.

The Sample Application
The sample temperature control application runs in both real-time and non-real-time mode to illustrate the benefits of Java RTS. The application contains a user interface in the form of a temperature gauge (see Figure 1). The green area represents a safe temperature, while the red areas represent the "danger zones."

Figure 1. The sample application updates a visual temperature gauge to show the current temperature of the nuclear reactor core.
Figure 2. This figure shows the output of the sample application when run in real-time mode.

The application consists of the main thread, which drives the gauge display, and two additional worker threads. The first worker thread simulates the temperature sensor, which is set to increase or decrease the temperature by one degree every two milliseconds. The temperature will increase if the cooling system is off, or decreases if it's on. The second worker thread is the temperature monitor thread, which will turn the cooling system on or off when the temperature gets close to the high or low thresholds, respectively.

In the real-time version of the system, the monitor thread is a RealtimeThread with a one-millisecond period. In the non-real-time version, this thread is a normal Java Thread that sleeps for one millisecond before checking the temperature. The code is otherwise the same in both instances; it simply looks for a command-line argument to indicate what type of thread to create.

To start the application in real-time mode, run the following command (see Figure 2 for the result):

> java –jar Temperature.jar -realtime

To start the application in non-real-time mode, run the following command (see Figure 3 for the result):

> java –jar Temperature.jar

Figure 3. This figure shows the output of the sample application when run in non-real-time mode (notice the warning messages in the console window).
Of course, you need a JSR-001 compliant Java RTS virtual machine to run it in real-time mode. If not, you'll have to take my word for it: the results are dramatic. The real-time version maintains a safe temperature regardless of what else happens in the system. However, with the non-real-time version, the temperature constantly veers into the danger zones.

With Java RTS and Solaris, you can build Java applications today that meet soft and hard real-time requirements on reasonably well equipped x86/x64 and SPARC-based systems. Just remember that real-time is not about speed and performance, but is instead about predictability and determinism. It's also not a simple matter of having a better garbage collector; Java RTS ensures that no system thread or process will interrupt your real-time Java threads, including processes external to the Java VM. Because of this, it’s important to choose a real-time Java VM that implements the RTSJ (JSR-001) specification, such as those offered by Sun, and IBM.

Eric Bruno is a New York-based consultant who has built high-volume Web applications, database systems, and real-time transactional systems in Java and C++. Visit www.ericbruno.com for more about him.
Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date