HomeDigital EditionSys-Con RadioSearch Java Cd
Advanced Java AWT Book Reviews/Excerpts Client Server Corba Editorials Embedded Java Enterprise Java IDE's Industry Watch Integration Interviews Java Applet Java & Databases Java & Web Services Java Fundamentals Java Native Interface Java Servlets Java Beans J2ME Libraries .NET Object Orientation Observations/IMHO Product Reviews Scalability & Performance Security Server Side Source Code Straight Talking Swing Threads Using Java with others Wireless XML

The Java development and runtime environment, with its "write once, run anywhere" paradigm, brings enormous advantages to the embedded industry. Java code is highly reliable, easily ported, and includes features such as Internet readiness, security, and the ability to download code at runtime to upgrade or extend applications.

As such, it's ideal for Internet appliances (such as set-top boxes, Internet screen phones, or handheld devices) as well as traditional embedded devices (such as printers, medical devices, measurement and control instruments, telecommunication and data-communication equipment now connecting to the Internet).

In Part 1 of this article (JDJ, Vol. 6, issue 9), we discussed some of the challenges of using Java for developing embedded systems and some of the solutions that are available to developers. In Part 2, we describe the benefits Java brings to the world of embedded software development. We also illustrate, based on a practical case study, how using Java for writing and running embedded software can benefit application developers.

Is Java Right for Your Embedded Device?
By asking the questions at the right, you should be able to determine if Java is the right development environment for your embedded device.

  1. Will you want to download code to the device?
  2. Will the device run in a network with a similar class of devices from other manufacturers or any other kind of devices?
  3. Will there be multiple third-party content providers for the device?
  4. Will user's experience (look and feel, stability, security) matter much?
  5. Are you working within a short-development time frame?
If you answered yes to any of these questions, Java may be the right choice for you. Here's why.

Java Benefits
The intrinsic advantages of Java are portability, reusability, and development life-cycle enhancements. They're invaluable for any software engineering project, including embedded software development. The benefits include:

  • Dynamic extensibility: A Java program can download code at runtime by fetching new class files and either replacing the same classes already loaded into memory or adding them to the application. Dynamic extensibility enables developers to extend the functionality of an application, upgrade classes with new versions of code, or simply fix software problems. It's also the base for implementing an application-management framework and a service-delivery platform.
  • Security: Strict code verification prior to execution ensures that code doesn't try to disregard the protections imposed by the language, build direct memory access pointers, or use the wrong object. Java applets also obey limitation rules (known as the sandbox concept) that Web browsers enforce to forbid access to system resources, such as files and network hosts. It's impossible in theory to introduce malicious code into a Java application. Java threads can't corrupt the execution space of another thread.
  • Portability: Java provides standard programming interfaces to OS-level services such as multithreading, networking, and graphics. This enables embedded system developers to write platform-independant code more quickly and easliy.
  • Reliability: Java provides the reliability that embedded systems require, such as the obligation of source structuring, strong compile and runtime verifications, and an efficient exception-handling mechanism. Java's memory-management mechanism removes sources of many problems associated with dynamic memory allocation, such as memory leaks or corrupted pointers. Java also relieves the embedded programmer of the hazardous object de-allocation task.
  • Reusable code: Java provides ease of code development, code reuse, and better code quality due to its true object orientation, simplicity, and development environment. A wide variety of affordable and efficient Java development tools are available as are many trained engineers.
Hands-on Porting Exercise
To illustrate how using Java for writing and running embedded software can benefit application developers, we selected a single healthy-sized example of a Java application - suitable and also useful for embedded applications. The example includes the following characteristics: it uses a simple graphical user interface, it's network-oriented, it's based on an existing version of C for easy comparison, and it's simple enough for a quick port, but large enough to be a significant case study.

Several aspects of this hands-on porting exercise are described below, basing comments on code snippets. The complete application source code is available for download on the JDJ Web site at www.sys-con.com/java/sourcec.cfm and can be freely used, modified, and distributed. The download package consists of application source code, documentation in javadoc format, Makefile, and precompiled class files and a .jar file.

The application we chose is called jtalk, a port of the Unix talk command. Here's an excerpt from the manual pages on the talk command on a FreeBSD system (obtained by typing man talk on the FreeBSD 4.3 system):

Talk is a visual communication program that copies lines from your terminal to that of another user. When first called, talk sends the message:

Message from [email protected]_machine... talk: connection requested by [email protected]_machine. talk: respond with: talk [email protected]_machine to the user you wish to talk to.

At this point, the recipient of the message should reply by typing:

talk [email protected]_machine

The talk utility is a two-way, screen-oriented communication program. Once communication is established, the two parties can type simultaneously, with their output displayed in separate regions of the screen.

The talk application sets up a peer-to-peer communication session with a remote user on another host. A talkd daemon has to be running on both the caller's and the callee's machines and act as a repository for active talk invitations from one party to another. The caller has to be able to leave an announcement on the callee's machine that an invitation exists and has to leave the invitation itself on the caller's own machine. Once the session is connected, the talk daemon isn't used; it's just peer-to-peer between the two talk programs.

Since talkd daemons exist for Unix machines only, a port of talkd in Java was also created as part of this case study so talk can be used on Windows machines as well as in a non-Unix embedded Java application environment, such as Wind River's VxWorks and Personal JWorks.

Note: There are two incompatible talk protocols of different ages. The older one uses UDP port 517 and is in use on Solaris. The newer one (which we chose to implement) uses UDP port 518 and is in use on BSD systems, such as FreeBSD or Wind River's BSD/OS. Technically, the port 517 protocol is called talk and the port 518 protocol is called ntalk. The port number 518 is currently hard-coded into jtalk and jtalkd. But it wouldn't help to change them to 517 because the older talk protocol on port 517 is incompatible. To run the jtalk program on your JVM, download the case study package, put jtalk.jar somewhere on your file system, add the location of jtalk.jar to your classpath, and invoke as follows:

java com.windriver.jtalk.jtalk {person} [{terminal}]
If the machine on which you're running jtalk doesn't run a talk daemon already, you'll have to first launch jtalkd with the following command:
java com.windriver.jtalk.jtalkd
The syntax for {person} can be any of the following:
username
[email protected]
hostname!username hostname:username
{terminal} is optional. It's required when responding to an invitation from someone with more than one login to be sure you get to the right one.

If you can't run multiple JVMs on your system (which is the case on most embedded RTOSes), the download package includes a basic "shell" with a simple self-explanatory GUI to help you launch the jtalkd and jtalk applications:

java com.windriver.jtalk.jtalkShell
If you want to recompile the source code, you can use the Makefile for GNU make included in the download package. The original C files from which jtalk was created are also included in the download package for your convenience. These files come from the FreeBSD 4.3 distribution.

Choosing to port an existing Unix application, coded as a C program, was deliberate so a head-to-head comparison could be easily done between the C code and the Java code. Table 1 summarizes the major characteristics of the two versions.

Table 1

The experience with jtalk showed that Java can be used more productively as a language, and as a programming environment, than C/C++ for certain types of applications, especially in the embedded area.

Some of the productivity advantages of Java are at the language level. For example:

  • The language's insistence on strong type checking promotes the careful arrangement of code into well-designed classes, saving effort when supporting the code later.
  • The jtalk program is cleanly organized in a directory structure com/windriver/jtalk following the package organization, leading to clean, easily understandable, and maintainable code. Each Java source file starts with:
package com.windriver.jtalk;
  • The C code for the talk program has a strange organization, with global variables shared by many modules. Most of the time it took to port the code was actually figuring out how that code worked. In addition, the use of global variables makes the application non-reentrant, which can be a major issue for many embedded systems. As a consequence, it's impossible to have multiple talk sessions on an embedded system.
  • The Java language's class inheritance (where a subclass extends a superclass, adding new features or overriding other features) and interface concepts (making implementations pluggable) both lead to more flexible reuse of existing Java code. In C, you usually have to modify to reuse code.
  • The file jtalkSessionClient.java (see Listing 1) defines an interface for a client session implemented among other interfaces in the AWT area, and makes the creation of GUIs much easier by the main class jtalk in jtalk.java (see Listing 2).
  • Exception handling is another fantastic built-in language feature that Java programs can efficiently take advantage of to manage abnormal situations or a rupture in the usual flow of execution. For example, jtalk defines a new RuntimeException called jtalkSessionException (see Listing 3) that is thrown by jtalk when a problem occurs in jtalkSession.java (see Listing 4) when trying to get the hostname information.
  • Another example of productivity gains from language-level features of Java is automatic garbage collection, freeing developers from tedious management of dynamic memory allocations, often prone to a generation of nasty bugs. Productivity advantages of Java from the overall programming environment are, for example:
  • The existence of the javadoc tool means that you can generate helpful documentation in HTML format for Java code right from the program source, leading to better documented source code and more available documentation during all engineering phases.
  • Figure 1 shows a snapshot of the HTML documentation page for the jtalkSession class,
  • The existence of standard API libraries for almost every imaginable application programming need leads to quick coding of applications. This also leads to smaller application code size, as seen in this case study.
  • If you're an application developer, you can write your application faster using Java and the preexisting standard APIs. If you're a system developer, however, you may find Java too abstract or high level, lacking features like direct access to memory or interrupt handling.
  • The most important preexisting API sets relevant to embedded applications running in PersonalJava types of platforms, such as Wind River's Personal JWorks, are networking and user interface APIs. Thus, if your application performs network communication and has a user interface, you should at least consider using Java to more productively code those portions of your application.
Figure 1
Figure  1:

To understand Java's suitability to write networking code, look at the original C source for the talk program. Note all the occurrences of signal() calls to set or clear a handler for the SIGALRM used to manage connection timeouts. Instead of setting a timeout on a socket the way it's done in the Java program, the C version sets a timeout for the process; if the timeout occurs, something is done. In one case, in invite.c, there's even a setjmp/longjmp pair, with the longjmp coming from the tail end of the SIGALRM handler used there. The effect is to create a crazy kind of "loop"(see "flowchart" in Listing 5).

This loops every 30 seconds, remaking the invitation repeatedly until at some point accept() manages to complete before the SIGALRM is delivered.

In the Java sources, we simply set a 30-second timeout on the ServerSocket. The equivalent accept() call then returns if there's no incoming connection before the 30 seconds elapse. We just have a simple loop in the Java sources (see Listing 6).

A Language and Platform
In this case study, we've demonstrated how Java can benefit embedded software application developers, especially those focusing on graphics and multithreaded networking. Java can benefit these users when used both as as a programming language and a development platform.

Java's standard, complete, and easy-to-use APIs allow developers to write portable, more compact, more efficient, simpler, and more easily maintainable code than in C, for which network, threading, and graphics APIs are usually proprietary. In addition, developers can also benefit from the language's advanced concepts such as object orientation, packages, exceptions, and strong typing, as well as from the advantages offered by Java's development platform, including documentation generation, cross-platform portability, and security features (which enable them to write more efficiently for better code).

Although it wasn't covered in this article, Java is ideal as an execution platform. Java's capability for dynamic and secure code updates provides the essential building block for creating an application and content-management framework that enables a service-delivery platform. Java's standardized API and portable code allows application developers to write platform-independent software content or services independently from embedded-system manufacturers. As long as applications are written to a Java specification that's compatible with the system's Java application environment, end users of such systems will be able to download, install, and run those applications on their systems.

Author Bios
Vincent Perrier is Wind River's product manager for Java platforms. He has a computer science and engineering degree from the University of Nantes in France. [email protected]

Steven Schwarz is a senior member of the technical staff at Wind River. Recently he has been making processor-independent ports of CLDC and MIDP-reference implementations to VxWorks. [email protected]

	



Listing 1: jtalkSessionClient.java 
public interface jtalkSessionClient 
{ 

     /** 
      * This method is called by the session to deliver a status 
  message 
      * to the client. 
      */ 
     public void     jtalkSessionStatus(String s); 

     /** 
      * This method is called by the session to get a character 
  typed 
      * by the local user of the session; each such character is 
      * transmitted by the session to the remote user of the ses 
    sion. 
      */ 
     public int     jtalkSessionITyped(); 

     /** 
      * This method is called by the session to inform the client 
  of a 
      * character typed by the remote user of the session. 
      */ 
     public void     jtalkSessionHeTyped(int b); 

     /** 
      * This method is called by the session when it is about to 
    shut 
      * down. 
      */ 
     public void     jtalkSessionEnding(); 
} 



Listing 2: jtalk.java 

public class jtalk 
     extends Frame 
     implements ActionListener, 
KeyListener, 
WindowListener, 
jtalkSessionClient 



Listing 3: jtalkSessionException.java 

public class jtalkSessionException 
     extends RuntimeException 
{ 
     /** 
      * Construct a jtalk session exception without a detail mes 
    sage. 
      */ 
     public jtalkSessionException() { 
super(); 
     } 

     /** 
      * Construct a jtalk session exception with a detail message. 
      */ 
     public jtalkSessionException(String s) { 
super(s); 
     } 
} 



Listing 4: jtalkSession.java 
try { 
     myInetAddr = java.net.InetAddress.getLocalHost(); 
     if (args[arg].equals("-host")) { 
         myInetAddr = java.net.InetAddress.getByName(args[arg + 1]); 
         arg += 2; 
         nargs -= 2; 
     } 
     myHostName = myInetAddr.getHostName(); 
} 
catch (Throwable t) { 
     t.printStackTrace(); 
     throw new jtalkSessionException("can't determine local host name"); 
} 
client.jtalkSessionStatus("[email protected]" + myHostName + " starting."); 


Listing 5: In the process context 
1. <announce invitation to callee's talkd daemon> 
2. <leave actual invitation on local talkd daemon> 
3. <use setjmp() to establish this as a jump-to point> 
4. <set SIGALRM timer for 30 seconds> 
5. <call accept() to accept an incoming connection> 
6. <cancel SIGALRM timer> 

Code snippet from invite.c: 
void 
invite_remote() 
{ 
... 
setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0); 
message("Waiting for your party to respond"); 
signal(SIGALRM, re_invite); 
(void) setjmp(invitebuf); 
while ((new_sockt = accept(sockt, 0, 0)) < 0) { 
if (errno == EINTR) 
continue; 
p_error("Unable to connect with your party"); 
} 

In the SIGALRM handler context: 
1. <announce the invitation again> 
2. <leave the invitation again> 
3. <use longjmp to jump to the point 3 in the process context> 

Code snippet from invite.c: 
void 
re_invite(signo) 
int signo; 
{ 
message("Ringing your party again"); 
waddch(my_win.x_win, '\n'); 
if (current_line < my_win.x_nlines - 1) 
current_line++; 
/* force a re-announce */ 
msg.id_num = htonl(remote_id + 1); 
announce_invite(); 
longjmp(invitebuf, 1); 
} 


Listing 6: jatlkSession.java 
void issueInvitation() 
     { 
... 
for (;;) { 
    if (current_idnum >= 0) { 
client.jtalkSessionStatus(RINGING); 
current_idnum++; 
    } 

    client.jtalkSessionStatus(ANNOUNCING); 

    msg.setMessage((byte) talkdMessage.ANNOUNCE, 
   current_idnum, 
   myUserName, 
   hisUserName, 
   hisTerminal, 
   server, 
   control, 
   myInetAddr); 
    controlTransaction(hisInetAddr); 
    remote_idnum = rs.getIdNum(); 

    if (rs.getAnswer() != talkdResponse.SUCCESS) { 
throw new jtalkSessionException("invitation rejected: " + 
rs.decodeAnswer()); 
    } 

    client.jtalkSessionStatus(INVITING); 

    msg.setMessage((byte) talkdMessage.LEAVE_INVITE, 
   current_idnum, 
   myUserName, 
   hisUserName, 
   hisTerminal, 
   server, 
   control, 
   myInetAddr); 
    controlTransaction(myInetAddr); 
    local_idnum = rs.getIdNum(); 

    client.jtalkSessionStatus(WAITING2); 

    try { 
data = server.accept(); 
data.setSoTimeout(1 * 1000); 
dataInput = data.getInputStream(); 
dataOutput = data.getOutputStream(); 
    } 
    catch (InterruptedIOException x) { 
current_idnum = remote_idnum; 
continue; 
    } 
    catch (Throwable t) { 
t.printStackTrace(); 
new jtalkSessionException("can't get connection"); 
    } 
    finally { 
msg.setMessage((byte) talkdMessage.DELETE, 
       local_idnum, 
       myUserName, 
       hisUserName, 
       hisTerminal, 
       null, 
       control, 
       myInetAddr); 
controlTransaction(myInetAddr); 

msg.setMessage((byte) talkdMessage.DELETE, 
       remote_idnum, 
       myUserName, 
       hisUserName, 
       hisTerminal, 
       null, 
       control, 
       myInetAddr); 
controlTransaction(hisInetAddr); 
    } 
    break; 
} 
     } 

  
 

All Rights Reserved
Copyright ©  2004 SYS-CON Media, Inc.
  E-mail: [email protected]

Java and Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. SYS-CON Publications, Inc. is independent of Sun Microsystems, Inc.