You are receiving this e-mail {e-mail address} because you elected to receive e-mail from Sun Microsystems, Inc. To update your communications preferences, please see the link at the bottom of this message. We respect your privacy and post our privacy policy prominently on our Web site http://sun.com/privacy/
  Welcome to the Java Technology Fundamentals Newsletter.
Java Technology Fundamentals
NEWSLETTER
May 2005
  This monthly newsletter provides a way for you to learn the basics of the Java programming language, discover new resources, and keep up-to-date on the latest additions to Sun Developer Network's New to Java Programming Center.

You can receive future issues of this newsletter in HTML or text:
http://developer.java.sun.com/subscription/

Note: For the code to compile in this issue of Fundamentals, you need to use the JDK 5.0 software.
http://java.sun.com/j2se/1.5.0/download.jsp

Contents
 
» Java Programming Language Basics: Formatting Basics with JFormattedTextField
» Making Sense of the Java Classes & Tools: Security Tools
» Java Bits: Version 1.5.0 or 5.0?
» Concurrent Programming with J2SE 5.0
» What's New on java.net: The Java Extension Mechanism
» What's New in the New to Java Technology Center: Updated Articles
» Sun's Java Technology Courses Special Offer
» For More Information

Java Programming Language Basics
 
Formatting Basics with JFormattedTextField by John Zukowski


The JFormattedTextField provides support for the input of formatted text. When the component is created, you define a mask for the input. That mask can be in the form of a java.text.Format object, as an AbstractFormatter, as an AbstractFormatterFactory, or in the form as an actual value, like a Date.

The system provides several abstract formatters for you to work with, depending upon the type of data you want a user to input. For instance, the NumberFormatter is available to enter numbers and the DateFormatter is available for entering dates. There is also a MaskFormatter for describing input with edit strings, like "XXX-XX-XXX" for a US social security number. If you want different display and edit formats, that's where the AbstractFormatterFactory comes into play.

For a JFormattedTextField, the validation magic is controlled by the focusLostBehavior property. This can be set to one of four values: COMMIT, COMMIT_OR_REVERT, REVERT, or PERSIST. When the component loses focus, you'll get one of four behaviors, the default being COMMIT_OR_REVERT. What COMMIT_OR_REVERT means is when the component loses focus, automatically call the commitEdit method internally. This parses the component's contents and throws a ParseException on error, reverting the contents to the most recent valid value. The COMMIT setting works similarly, but leaves the invalid contents within the field, allowing the user to modify the setting. A REVERT setting always reverts the value, while PERSIST essentially does nothing. When set to PERSIST, you should manually call commitEdit yourself to see if the contents are valid before using the contents.

For starters, let's use the JFormattedTextField to accept input that should be internationalized. This includes all forms of dates, times, and numbers, basically, anything whose format can be acquired form a DateFormat or NumberFormat object. If, instead, you provide a Date object or Number subclass to the JFormattedTextField constructor, the component passes the input String to the constructor of that object type to do the input validation. Instead, you should work with the InternationalFormatter class in the java.swing.text package by passing a DateFormat or NumberFormat into the constructor. This allows you to specify long vs. short form for dates and times, and currency, percentage, floats, and integers for numbers.

To demonstrate, the example below accepts date and time input. From top to bottom, the inputs are short date format for default locale, full date format for US English, medium date format for Italian, day of week in French, and short time format for the default locale. To start the program in a different locale, you can set the user.language and user.country settings from the command line with a command similar to the following:

java -Duser.language=fr -Duser.country=FR DateInputSample, though this only alters the valid input for those formats without a specific locale set.
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.event.*;
import java.awt.*;
import java.text.*;
import java.util.*;

public class DateInputSample {
  public static void main(String args[]) {
    Runnable runner = new Runnable() {
      public void run() {
        JFrame frame = new JFrame("Date/Time Input");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JLabel label;
        JFormattedTextField input;
        JPanel panel;

        BoxLayout layout =
          new BoxLayout(frame.getContentPane(), BoxLayout.Y_AXIS);
        frame.setLayout(layout);

        Format shortDate =
          DateFormat.getDateInstance(DateFormat.SHORT);
        label = new JLabel("Short date:");
        input = new JFormattedTextField(shortDate);
        input.setValue(new Date());
        input.setColumns(20);
        panel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        panel.add(label);
        panel.add(input);
        frame.add(panel);

        Format fullUSDate =
          DateFormat.getDateInstance(DateFormat.FULL, Locale.US);
        label = new JLabel("Full US date:");
        input = new JFormattedTextField(fullUSDate);
        input.setValue(new Date());
        input.setColumns(20);
        panel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        panel.add(label);
        panel.add(input);
        frame.add(panel);

        Format mediumItalian =
          DateFormat.getDateInstance(DateFormat.MEDIUM, 
		    Locale.ITALIAN);
        label = new JLabel("Medium Italian date:");
        input = new JFormattedTextField(mediumItalian);
        input.setValue(new Date());
        input.setColumns(20);
        panel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        panel.add(label);
        panel.add(input);
        frame.add(panel);

        Format dayOfWeek = new SimpleDateFormat("E", Locale.FRENCH);
        label = new JLabel("French day of week:");
        input = new JFormattedTextField(dayOfWeek);
        input.setValue(new Date());
        input.setColumns(20);
        panel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        panel.add(label);
        panel.add(input);
        frame.add(panel);

        Format shortTime = 
          DateFormat.getTimeInstance(DateFormat.SHORT);
        label = new JLabel("Short date:");
        input = new JFormattedTextField(shortTime);
        input.setValue(new Date());
        input.setColumns(20);
        panel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        panel.add(label);
        panel.add(input);
        frame.add(panel);

        frame.pack();
        frame.setVisible(true);
      }
    };
    EventQueue.invokeLater(runner);
  }
}

Date/Time Input

Numbers work similarly to dates, just with the java.text.NumberFormat class, instead of the DateFormat. The localization that can be done here is with the getCurrencyInstance, getInstance, getIntegerInstance, getNumberInstance, and getPercentInstance methods. The NumberFormat class deals with the placement of the necessary commas, periods, percent signs, and so forth. While inputting the numbers, extra characters like commas for thousands aren't required. The component naturally adds them after the fact where appropriate. The listing here shows the resulting program. Each input field starts with a value of 2424.50. Notice the position of decimal points and commas and how it differs from locale to locale. Properly set, your users won't have to worry. In the case of the integer version, the input value is rounded. When setting the contents of a JFormattedTextField, use the setValue method, not the setText method. This will ensure the text contents are validated.
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.event.*;
import java.awt.*;
import java.text.*;
import java.util.*;

public class NumberInputSample {
  public static void main(String args[]) {
    Runnable runner = new Runnable() {
      public void run() {
        JFrame frame = new JFrame("Number Input");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Font font = new Font("SansSerif", Font.BOLD, 16);

        JLabel label;
        JFormattedTextField input;
        JPanel panel;

        BoxLayout layout =
          new BoxLayout(frame.getContentPane(), BoxLayout.Y_AXIS);
        frame.setLayout(layout);

        Format currency =
          NumberFormat.getCurrencyInstance(Locale.UK);
        label = new JLabel("UK Currency:");
        input = new JFormattedTextField(currency);
        input.setValue(2424.50);
        input.setColumns(20);
        input.setFont(font);
        panel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        panel.add(label);
        panel.add(input);
        frame.add(panel);

        Format general = NumberFormat.getInstance();
        label = new JLabel("General/Instance:");
        input = new JFormattedTextField(general);
        input.setValue(2424.50);
        input.setColumns(20);
        input.setFont(font);
        panel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        panel.add(label);
        panel.add(input);
        frame.add(panel);

        Format integer =
             NumberFormat.getIntegerInstance(Locale.ITALIAN);
        label = new JLabel("Italian integer:");
        input = new JFormattedTextField(integer);
        input.setValue(2424.50);
        input.setColumns(20);
        input.setFont(font);
        panel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        panel.add(label);
        panel.add(input);
        frame.add(panel);

        Format number =
               NumberFormat.getNumberInstance(Locale.FRENCH);
        label = new JLabel("French Number:");
        input = new JFormattedTextField(number);
        input.setValue(2424.50);
        input.setColumns(20);
        input.setFont(font);
        panel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        panel.add(label);
        panel.add(input);
        frame.add(panel);

        label = new JLabel("Raw Number:");
        input = new JFormattedTextField(2424.50);
        input.setColumns(20);
        input.setFont(font);
        panel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        panel.add(label);
        panel.add(input);
        frame.add(panel);
        frame.pack();
        frame.setVisible(true);
      }
    };
    EventQueue.invokeLater(runner);
  }
}

Number Input

The last of the five JFormattedTextField examples here initializes the component with a double. The value 2424.50 is auto-boxed into a Double object. There's nothing wrong with passing an object to the constructor. Playing with the input field though will reveal some irregularities while entering values. It seems to always start with one decimal point, even though more input digits are accepted. Instead of using a Format object to go from text to Object and back, the Double constructor that accepts a String is used instead.

When you pass in a java.text.Format object to the JFormattedTextField constructor, this internally is mapped to either a DateFormatter or NumberFormatter object. Both of these are subclasses of the InternationalFormatter class. The inner class named JFormattedTextField.AbstractFormatterFactory manages the use of the formatter objects within JFormattedTextField. The factory will install() the formatter as the user enters the JFormattedTextField and uninstall() it upon departure, ensuring the formatter is active in only one text field at a time. These install and uninstall methods are inherited by the formatter classes from the JFormattedTextField.AbstractFormatter, superclass of all formatters.

Beyond numbers and dates, the JFormattedTextField supports user input following a pattern or mask. For instance, if an input field is a social security number (SSN), it has a typical pattern of number, number, number, dash, number, number, dash, number, number, number, number. With the help of the MaskFormatter class, you can specify the mask using characters found in the following table. So, an SSN would be created with a formatter of new MaskFormatter("###'-##'-####"). The apostrophes in the mask mean the character after each is treated literally, in this case as a dash. You have the option of passing this formatter to the JFormattedTextField constructor, or configuring the text field with the setMask method.
CHARACTER    DESCRIPTION
# Matches numeric character (Character.isDigit()) H Matches hexadecimal number (0-9 + a-f + A-F) A Matches alphanumeric character (Character.is LetterOrDigit()) ? Matches alphabetic character (Character.isLetter()) U Matches uppercase letter, maps lowercase to uppercase L Matches lowercase letter, maps uppercase to lowercase * Wildcard, match any character ' Escape character to have literal strings/separators in input field.
To demonstrate, the following class includes two JFormattedTextField components, one to accept US social security numbers, and the other US-formatted phone numbers. The SSN field starts with an initial value, while the phone number doesn't.
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.event.*;
import java.awt.*;
import java.text.*;
import java.util.*;

public class MaskInputSample {
  public static void main(String args[]) {
    Runnable runner = new Runnable() {
      public void run() {
        JFrame frame = new JFrame("Mask Input");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JLabel label;
        JFormattedTextField input;
        JPanel panel;
        MaskFormatter formatter;

        BoxLayout layout =
          new BoxLayout(frame.getContentPane(), BoxLayout.Y_AXIS);
        frame.setLayout(layout);

        try {
          label = new JLabel("SSN");
          formatter = new MaskFormatter("###'-##'-####");
          input = new JFormattedTextField(formatter);
          input.setValue("123-45-6789");
          input.setColumns(20);
          panel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
          panel.add(label);
          panel.add(input);
          frame.add(panel);
        } catch (ParseException e) {
          System.err.println("Unable to add SSN");
        }

        try {
          label = new JLabel("US Phone");
          formatter = new MaskFormatter("'(###')' ###'-####");
          input = new JFormattedTextField(formatter);
          input.setColumns(20);
          panel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
          panel.add(label);
          panel.add(input);
          frame.add(panel);
        } catch (ParseException e) {
          System.err.println("Unable to add Phone");
        }

        frame.pack();
        frame.setVisible(true);
      }
    };
    EventQueue.invokeLater(runner);
  }
}

Mask Input

The MaskFormatter does provide some customization options. By default, the formatter is in overwrite mode, so as you type, the entered digits will replace each number/space in the input field. Set the overwriteMode property to false to disable this. Typically this isn't necessary, though for entering long dates it can be helpful. If you wish to have a different character as the placeholder character, before a position is filled in mask, set the placeholderCharacter property of the MaskFormatter.

Making Sense of the Java Classes & Tools
 
Security Tools


These security tools help you set security policies on your system and create applications that can work within the scope of security policies set at remote sites.
   Tool Name 	Brief Description

   keytool      Manage keystores and certificates.
   jarsigner 	Generate and verify JAR signatures.
   policytool 	GUI tool for managing policy files.
These security tools help you obtain, list, and manage Kerberos tickets.

Tool NameBrief Description
kinitTool for obtaining Kerberos v5 tickets. Equivalent functionality is available on the Solaris operating system through the kinit tool.
tklistCommand-line tool to list entries in credential cache and key tab. Equivalent functionality is available on the Solaris operating environment through the klist tool.
ktabCommand-line tool to help the user manage entires in the key table. Equivalent functionality is available on the Solaris operating system through the kadmin tool.
Read more

Java Bits
 
Version 1.5.0 or 5.0? by Sun Staff


Both version numbers 1.5.0 and 5.0 are used to identify this release of the Java 2 Platform Standard Edition. Version 5.0 is the product version, while 1.5.0 is the developer version. The number 5.0 is used to better reflect the level of maturity, stability, scalability and security of the J2SE.

The number 5.0 was arrived at by dropping the leading 1. from 1.5.0. Where you might have expected to see 1.5.0, it is now 5.0, and where it was 1.5, it is now 5.

Version 5.0 Used in Platform and Product Names

Version 5.0 is used in the platform and product names as given in this table:

 Full NameAbbreviation
Platform nameJava 2 Platform Standard Edition 5.0J2SE 5.0
Products delivered
under the platform
J2SE Development Kit 5.0
J2SE Runtime Environment 5.0
JDK 5.0
JRE 5.0


Due to significant popularity within the Java developer community, the development kit has reverted back to the name JDK from Java 2 SDK (or J2SDK), and the runtime environment has reverted back to JRE from J2RE. Notice that JDK stands for J2SE Development Kit to distinguish it from the J2EE Development Kit. The name Java Development Kit is no longer used, and has not been officially used since 1.1, prior to the advent of J2EE and J2ME.

As before, the 2 in Java 2 Platform Standard Edition indicates the second generation Java platform, introduced with J2SE 1.2. This generation number is also used with J2EE and J2ME.

Version 1.5.0 Used by Developers

J2SE also keeps the version number 1.5.0, or 1.5, in some places that are visible only to developers, or where the version number is parsed by programs. As mentioned, 1.5.0 refers to exactly the same platform and products numbered 5.0. Version numbers 1.5.0 and 1.5 are used at:
  • java -version (among other info, returns java version 1.5.0)
  • java -full version (returns java full version 1.5.0-b64)
  • javac -source 1.5 (javac -source 5 also works)
  • java.version system property
  • java.vm.version system property
  • @since 1.5 tag values
  • jdk1.5.0 installation directory
  • jre1.5.0 installation directory
  • http://java.sun.com/j2se/1.5.0
  • http://java.sun.com/j2se/5.0
Read more

Concurrent Programming with J2SE 5.0
 
By Qusay H. Mahmoud


Java is a multithreaded programming language that makes programming with threads easier, by providing built-in language support for threads. The built-in primitives however, such as synchronized blocks, Object.wait, and Object.notify, are insufficient for many programming tasks. This leads developers to implement their own high-level synchronization facilities, but given the difficulty of concurrency issues, their implementations may not be correct, efficient, or high quality.

The Java 2 Platform, Standard Edition release 5.0 (J2SE 5.0), which is also known as Tiger, has provided a new path to multithreading in the Java programming language. The original mechanisms for coordinating threads with wait and notify are now enhanced with new and sophisticated mechanisms for working with threads. The new mechanisms are part of the java.util.concurrent package, which offers a standard set of concurrency utilities that will ease the task of developing multithreaded applications and servers. In addition, such standards will improve the quality of such applications. The package has been defined through the Java Community Process as JSR 166: Concurrency Utilities.

This article provides an overview and an introductory tutorial to the new concurrency mechanisms that have been added to J2SE 5.0. It helps developers get started using the new java.util.concurrent package and its subpackages.

Limitations of Built-in Synchronization in J2SE 1.4.x

When writing multithread applications, the issues that may create difficulties are related to data synchronization; these are the errors that make design harder, and such errors are hard to detect. Built-in synchronization (methods and blocks) are fine for many lock-based applications, but they do have their own limitations, such as:
  • No way to back off from an attempt to acquire a lock that is already held, or to give up after waiting for a specified period of time, or to cancel a lock attempt after an interrupt.
  • No way to alter the semantics of a lock, for example, with respect to reentrancy, read versus write protection, or fairness.
  • No access control for synchronization. Any method can perform synchronized(obj) for any accessible object.
  • Synchronization is done within methods and blocks, thus limiting use to strict block-structured locking. In other words, you cannot acquire a lock in one method and release it in another.
Such problems can be overcome by using utility classes to control locking, such as Mutex, which is another term for a lock. A mutex, however, doesn't nest like synchronization methods or blocks.

Read the rest of this article

What's New on java.net
 
The Java Extension Mechanism by Thomas Künneth


A huge number of publicly available packages extends the functionality of the Java core platform. Some of them provide access to features of the underlying operating system that are not available through the standard class library, such as missing GUI components, or reader and writer classes for important file formats. Others are exciting technologies in their own right, like Spring, Hibernate or Struts.

Sometimes installing them is a bit tricky, requiring you to modify the class path of your application or tweak options passed to the Java launcher. Others utilize a handy feature called the Java Extension Mechanism. Libraries loaded through the extension mechanism can be accessed by any Java program without further prerequisites besides copying some files to certain directories. This article explains how the Extension Mechanism works and discusses the steps required to implement your own so-called optional packages.

The Class Path

The virtual machine uses the concept of a class path, which is a set of directories and .zip or .jar archives. To find classes (as well as other resources like properties files, images, or audio content) the Java runtime looks in all locations specified in the class path to find the required resource.

Early versions of Java relied heavily on an environment variable called CLASSPATH that stored these locations. It is easy to modify this variable, perhaps too easy: setting the class path this way turned out to be error-prone, as changes usually affected other applications. Another shortcoming of this approach was the missing distinction between user (third-party) and system classes. Today there is no need to use the CLASSPATH environment variable.

Since Java 1.2, the virtual machine has distinguished between three types of classes: bootstrap classes, extension classes, and user classes. Each type has its own individual search path that can be modified separately. All three parts together make up the class path. It is worth mentioning, however, that the user class path is commonly referred to as simply "the class path."

The difference between extension classes and user classes may not be clear at first sight, as they both are implemented by third-party developers, and hence do not belong to the core Java classes. The difference is that user classes do not take advantage of the extension mechanism. Additionally, the way that extension classes are found by the virtual machine is different.

The boot class path specifies where core system classes are searched. The system property sun.boot.class.path stores these locations. It generally should not be necessary to change them, but there is a non-standard option of the Java launcher, -Xbootclasspath, that allows you to use alternative core system classes.

How User Classes Are Found

The user class path specifies where user classes and resources are searched. A simple program consisting of one class called Test is invoked through:

java Test

This assumes you use the standard Java launcher. The class path defaults to the current directory, so Test is found easily (if the current directory contains Test.class).

A program consisting of two .jars (the main application in MyApp.jar and a set of utility classes in MyUtils.zip) is invoked through:

java -classpath MyApp.jar;MyUtils.zip myapp.MyAppMain

The path separator is ; on Windows, while UNIX variants like Mac OS X and Linux use : instead.

Using -classpath completely overrides the default setting; therefore, the current directory is not part of the class path. Consequently, to access classes that are not part of the specified .jar or .zip archives, the directory containing them must be added to the user class path with the -classpath option.

Sharing .jar Archives

It is common practice to have a Main-Class: attribute in the main application .jar's manifest file so the application can be launched by typing java -jar MyApp.jar. In this case, the .jar file is the source for all user classes. Any other class path option is ignored.

To gain access to classes and resources stored in utility class .jars, you must add a Class-Path: attribute to your application's manifest file. Its value contains a space-delimited list of relative URLs referencing libraries your application wishes to use. These URLs are assumed to point to directories if they end with the / character. Otherwise they are assumed to refer to .jars.

To share a library among multiple projects, you could add its location to the class paths of these programs using -classpath or Class-Path: in the manifest file of each program. This can be a cumbersome task if several projects are involved. If we used the old-style CLASSPATH environment variable, it would have been sufficient to append the location of the library--no need to explicitly reference it with each application wishing to use it. But there must be a similar feature in recent Java versions, right?

Read the rest of this article

What's New in the New to Java Technology Center
 
Updated Articles


Articles in the New to Java Technology Programming Center have been updated to reflect newer operating systems, and the latest J2SE software download.

Make sense of many Java technologies and acronyms with Unraveling Java Terminology and the Java Concept Map, and learn how to set up the lastest Java platform software using Getting Started as a guide:

Sun's Java Technology Courses Special Offer
 
For a limited time, register for one of our five most popular Java technology training courses to be eligible to receive one of our five most requested giveaway items.

Qualifying Java Technology Courses
  • Developing Applications for the J2EE Platform (FJ-310)
  • Java Programming Language (SL-275)
  • Web Component Development With Servlet and JSP Technologies (SL-314)
  • Architecting and Designing J2EE Applications (SL-425)
  • Object-Oriented Analysis and Design Using UML (OO-226)
Giveaway Items
  • iPod Shuffle
  • Sun Java Bomber Jacket
  • MP3 Watch
  • Sony PlayStation 2
  • Biometric Flash Drive
Within two weeks after attending the class, you will receive an email from Sun's agency with information about how to order your Top 5 giveaway item. You will be asked to provide your shipping information as well as your choice of one of the five gifts items. After submission, you will receive the item within 2-3 weeks.

Offer is good while quantities last. There are limited quantities of each of the 5 items. If the item you want is no longer available you will have to choose from the remaining items.

For More Information
 

Downloading the Java 2 Platform
 
For most Java development, you need the class libraries, compiler, tools, and runtime environment provided with the J2SE development kit.

Rate and Review
Tell us what you think of the content of this page.
Excellent   Good   Fair   Poor  
Comments:
If you would like a reply to your comment, please submit your email address:
Note: We may not respond to all submitted comments.
Comments? Send your feedback on the Java Technology Fundamentals Newsletter to: fundamentals_newsletter@sun.com

Find archived issues of the following Java technology developer newsletters or manage your current newsletter subscriptions: https://softwarereg.sun.com/registration/developer/en_US/subscriptions

Subscribe to the following newsletters for the latest information about technologies and products in other Java platforms:
  • Core Java Technologies Newsletter. Learn about new products, tools, resources, and events of interest to developers working with core Java technologies.
  • Mobility Developer Newsletter. Learn about the latest releases, tools, and resources for developers working on wireless and Java Card technologies and applications.
  • Core Java Technologies Tech Tips (formerly JDC Tech Tips) Get expert tips, sample code solutions, and techniques for developing in the Java 2 Platform, Standard Edition (J2SE)
You can subscribe to these and other JDC publications on the JDC Newsletters and Publications page

IMPORTANT: Please read our Terms of Use, Privacy, and Licensing policies:
http://www.sun.com/share/text/termsofuse.html
http://www.sun.com/privacy/
http://developer.java.sun.com/berkeley_license.html

© 2005 Sun Microsystems, Inc. All Rights Reserved. For information on Sun's trademarks see: http://sun.com/suntrademarks
Java, J2EE, J2SE, J2ME, and all Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries.

To update your Sun subscription preferences or unsubscribe to Sun news services, click here or use this link https://softwarereg.sun.com/registration/developer/en_US/subscriptions

Sun Microsystems, Inc. 10 Network Circle, MPK10-209 Menlo Park, CA 94025 US