Return-Path: <env_33208391174049728@hermes.sun.com>
Received: from po10.mit.edu (po10.mit.edu [18.7.21.66])
	by po10.mit.edu (Cyrus v2.1.5) with LMTP; Tue, 08 Apr 2003 14:07:41 -0400
X-Sieve: CMU Sieve 2.2
Received: from fort-point-station.mit.edu by po10.mit.edu (8.12.4/4.7) id h38I7ZKB015911; Tue, 8 Apr 2003 14:07:35 -0400 (EDT)
Received: from hermes.sun.com (hermes.sun.com [64.124.140.169])
	by fort-point-station.mit.edu (8.12.4/8.9.2) with SMTP id h38I28Ve016339
	for <alexp@mit.edu>; Tue, 8 Apr 2003 14:02:09 -0400 (EDT)
Date: 8 Apr 2003 09:15:43 -0800
From: "JDC Tech Tips" <sunmail@hermes.sun.com>
To: alexp@mit.edu
Message-Id: <33208391174049728@hermes.sun.com>
Subject: Core Java Technologies Tech Tips, April 8, 2003 (Destroying Objects, Preprocessing)
Mime-Version: 1.0
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit
X-Mailer: SunMail 1.0
X-Spam-Score: 2.3
X-Spam-Level: ** (2.3)
X-Spam-Flag: NO
X-Scanned-By: MIMEDefang 2.28 (www . roaringpenguin . com / mimedefang)

<!DOCtype HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Core Java Technologies Technical Tips</title>

<style type="text/css">

code {color: #333333; font-family: verdana, courier, monospace; font-size: 10pt}
pre {color: #333333; font-family: verdana, courier, monospace; font-size: 10pt}
body, div, span {color: #333333; font-family: arial, helvetica, sans-serif; font-size: 10pt}
td, th {color: #333333; font-family: arial, helvetica, sans-serif; font-size: 10pt}
tr {color: #333333; font-family: arial, helvetica, sans-serif; font-size: 10pt}
table {font-family: arial, helvetica, sans-serif; font-size: 10pt}
p {color: #333333; font-family: arial, helvetica, sans-serif; font-size: 10pt}
li {color: #333333; font-family: arial, helvetica, sans-serif; font-size: 10pt}
br {color: #333333; font-family: arial, helvetica, sans-serif; font-size: 10pt}
div {color: #666699; font-family: arial, helvetica, sans-serif; font-size: 10pt}
sup {font-family: arial, helvetica, sans-serif; font-size: 5pt}
h3 {color: #666699; font-family: arial, helvetica, sans-serif; font-size: 11pt}
h4, b {color: #666699; font-family: arial, helvetica, sans-serif; font-size: 10pt}
blockquote, input, select {color: #333333; font-family: arial, helvetica, sans-serif; font-size: 10pt}
ul, ol {color: #333333; font-family: arial, helvetica, sans-serif; font-size: 10pt}
a:link {font-size: 10pt; font-family: arial, helvetica, sans-serif; color:#666699 }
span.purple {font-weight: bold; color: #666699; font-family: arial, helvetica, sans-serif; font-size: 10pt}
span.small {font-size: 8pt; font-family: arial, helvetica, sans-serif; color:#333333 }
span.link {font-size: 8pt; font-family: arial, helvetica, sans-serif; color:#666699 }
</style>

</head>

<body bgcolor="#ffffff">
<a name="top"></a>
<table border="0" cellpadding="0" cellspacing="0" width="611">
<tr>
<td colspan="3" bgcolor="#cccccc" width="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" border="0" alt="."></td>
</tr>

<tr>
<td bgcolor="#cccccc" width="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" border="0" alt="."></td>

<td>
<table border="0" cellpadding="0" cellspacing="0" width="611">
<tr>
<td colspan="2"><a href="http://bulkmail2.sun.com/CTServlet?id=1049817986427"><img src="http://developer.java.sun.com/images/headers/core_ttips_hdr.jpg" width="611" height="160" alt="Core Java Technologies Technical Tips" border="0"></a></td>
</tr>

<tr>
<td colspan="2" bgcolor="#cccccc" width="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" border="0" alt="."></td>
</tr>

<!-- ================== -->
<!-- Start Main Content -->
<!-- ================== -->

<tr>
<td height="20">&nbsp;&nbsp;&nbsp;<a href="http://bulkmail2.sun.com/CTServlet?id=1049817986439" style="text-decoration:none;">View this issue as simple text</a></td>
<td align="right" height="20"><span class="purple">April 8, 2003</span>&nbsp;&nbsp;&nbsp;&nbsp;</td>
</tr>

<tr><td colspan="2">

<table border="0" cellpadding="10" cellspacing="0" width="100%">
<tr>
<td>
     
<form method="get" action="http://search.java.sun.com/search/java/">   
<table border="0" cellpadding="3" cellspacing="0" width="100%">
<tr> 
<td align="left" valign="middle" width="20%"><h3>In this Issue</h3></td>
              
<td valign="middle" align="right" width="70%">
<font size="2">
<input type="text" size="15" maxlength="128" name="qt"></font></td>
            
<td valign="middle" width="55">
<input type="image" src="http://developer.java.sun.com/images/v4a_search.gif" alt="Search" value="search" border="0" width="55"></td>
</tr>
</table>
</form>

<p>
Welcome to the Core Java Technologies Tech Tips, April 8, 2003. Here you'll get tips on using core Java technologies and APIs, such as those in Java 2 Platform, Standard Edition (J2SE).
</p>

<p>
This issue covers:
</p>

<p>
<a href="#1"><img src="http://developer.java.sun.com/images/anchor.gif" border="0" alt=".">Destroying Objects</a>
<br>    
<a href="#2"><img src="http://developer.java.sun.com/images/anchor.gif" border="0" alt=".">Preprocessing and the Java Language</a>
</p>

<p>
These tips were developed using Java 2 SDK, Standard Edition, v 1.4. 
</p>

<p>
This issue of the Core Java Technologies Tech Tips is written by Glen McCluskey.
</p>

<table width="100%" border="0" cellspacing="0" cellpadding="0" align="center">

<!-- Grey Horizontal Line Begins Here -->

<tr>
<td bgcolor="#cccccc" height="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" alt="." border="0"></td>
</tr>
</table> 

<table width="100%" border="0" cellspacing="0" cellpadding="0" align="center">

<!-- Grey Horizontal Line Begins Here -->

<tr>
<td bgcolor="#cccccc" height="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" alt="." border="0"></td>
</tr>
</table> 

<!-- Grey Horizontal Line ends Here -->

<a name="1"></a>

<h3>DESTROYING OBJECTS</h3>

<p>
In Java programming, you create class objects and arrays using 
the <code>new</code> operator. Such creation involves allocation of space, 
followed by a constructor call (for classes) to initialize the 
object. This tip examines what happens at the other end, that is,
when objects are destroyed.
</p>

<p>
Let's start by presenting a comparative example that shows how
another object-oriented language (C++) handles object destruction:
</p>

<pre>
    #include &lt;cstdio&gt;
    
    using namespace std;
    
    class A {
    public:
        A() {
            printf(&quot;call A::A %lx\n&quot;, (unsigned long)this);
        }
        ~A() {
            printf(&quot;call A::~A %lx\n&quot;, (unsigned long)this);
        }
    };
    
    void f() {
        A a;
    }
    
    int main() {
        A* ap = new A;
        f();
        delete ap;
    }
</pre>

<p>
Class A has a destructor <code>A::~A</code>. It's called when a stack-based
object, such as the one allocated in the <code>f</code> function, goes out of
scope. A destructor is also called when an object is explicitly
deleted through the delete operator -- this is also illustrated 
in the program. The destructor is responsible for any 
class-specific cleanup that needs to be done. After the 
destructor is called, the space for the object is reclaimed.
</p>

<p>
The output of the program looks like this:
</p>

<pre>
    call A::A 7a32c8
    call A::A 12ff50
    call A::~A 12ff50
    call A::~A 7a32c8
</pre>

<p>
The output shows the memory addresses of objects at construction 
and destruction time.
</p>

<p>
The Java language handles things a little differently. In the
first place, there are no stack-based objects, only references to
objects. In other words, objects are allocated dynamically, and
references (pointers) to those objects may be stored on the stack.
</p>

<p>
Another really big difference is that there is no delete operator
corresponding to the new operator that is used to allocate 
objects. Unreferenced objects (&quot;garbage&quot;) are automatically 
reclaimed as needed, through a process known as garbage 
collection. For example, in this code:
</p>

<pre>
    void f() {
        String str = new String();
    }
</pre>

<p>
the string object becomes garbage as soon as the f method 
completes execution. There is no way for the program containing f 
to reference the string, and so the memory used for the string 
object can be reclaimed. The actual process of garbage collection 
is scheduled in a way to minimize garbage collector overhead. It
will probably take place at a later time (or not at all). 
</p>

<p>
When garbage collection happens, the Java virtual machine<a href="#JVM">*</a> 
determines which objects in the application are live, that is, 
which objects are reachable from running code. Objects that are 
not reachable are subject to reclamation, and their memory is 
reused. Because there is no delete operator, and no notion of 
stack-based objects going out of scope, it is only at garbage 
collection time that a call to a destructor is meaningful.
</p>

<p>
This model has several implications. One is that you don't 
usually need to worry about space management issues. There is
no delete operator available, and it's usually a bad idea to
explicitly invoke garbage collection.
</p>

<p>
Sometimes it's useful to deliberately nullify object references, 
to help out the garbage collector. For example, if you have a
stack of object references, and you pop an element from the 
stack, it's important to set the just-vacated stack slot 
reference to null. Here's some sample code:
</p>

<pre>
        public Object pop() { 
                Object obj = stack[stackptr]; 
                stack[stackptr--] = null; 
                return obj; 
        }
</pre>

<p>
Popping an element from the stack means that the element is no 
longer on the stack, but the object reference will linger unless 
nullified or overwritten by a subsequent stack push. The 
collection classes take care of this operation for you.
</p>

<p>
Another point concerns management of system resources. When
garbage collection takes place, unused object and array space is
reclaimed. But what happens if an object makes reference to
other system resources, such as file descriptors?  How are such
resources reclaimed? One way of handling this situation is to
define an explicit <code>close()</code> or <code>cleanup()</code> method, which an 
application must call when done with an object. This method will 
take care of freeing system resources.
</p>

<p>
For more information about garbage collection, see section 12.1, 
Garbage Collection, section 12.2, A Simple Model, section 12.3, 
Finalization, and section 12.4, Interacting With the Garbage 
Collector, in &quot;<a href="http://bulkmail2.sun.com/CTServlet?id=1049817986366">The Java Programming Language Third Edition</a>&quot; by 
Arnold, Gosling, and Holmes.
</p>

<table width="100%" border="0" cellspacing="0" cellpadding="0" align="center">
<tr>
<td>
<div align="right">
<a href="#top">back to top<img src="http://developer.java.sun.com/images/back_to_top.gif" border="0" alt="image"></a>
</div>
</td>
</tr>

<tr>
<td bgcolor="#ffffff" height="2"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" alt="." border="0"></td>
</tr>

<!-- Grey Horizontal Line Begins Here -->

<tr>
<td bgcolor="#cccccc" height="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" alt="." border="0"></td>
</tr>
</table> 

<!-- Grey Horizontal Line ends Here -->

<a name="2"></a>

<h3>PREPROCESSING AND THE JAVA LANGUAGE</h3>

<p>
The widely-used programming languages C and C++ make heavy use of
what is called a preprocessor. The preprocessor makes an initial
scan over the source code, and certain preprocessor directives 
are treated in a special way. For example, the directive:
</p>

<pre>
    #define X 37
</pre>

<p>
results in the token <code>X</code> being replaced with <code>37</code> throughout the 
code. This feature is used to specify global constants in an 
application.
</p>

<p>
The preprocessor is used to define constants, to include the
contents of other source files (header files), to specify
conditional compilation, and so on. Preprocessing is a useful
mechanism, but it does have some problems associated with it. The 
Java language has no preprocessor, and because of this, it takes 
a different approach in these areas. 
</p>

<p>
Let's start by looking at the preprocessor <code>#include</code> directive in 
C and C++. This directive is used to include the contents of one 
file in another, like this:
</p>

<pre>
    #include &lt;stdio.h&gt;
</pre>

<p>
Typically you use a directive like this to gain access to 
constants and function declarations found in a header file such 
as <code>stdio.h</code>. The Java approach uses import declarations instead 
of <code>#include</code>:
</p>

<pre>
    import java.util.*;

    import java.io.FileInputStream;
</pre>

<p>
and there is also an implicit declaration:
</p>

<pre>
    import java.lang.*;
</pre>

<p>
supplied for you at the top of every Java source file. 
Information such as constants, typically found in header files,
is folded into Java source code.
</p>

<p>
Import declarations do not use textual inclusion, but simply make
the types in the specified package available. This approach tends
to be much cleaner than actually importing huge masses of source
code from a large number of header files.
</p>

<p>
Another way that a C/C++ preprocessor is used is to define global
constants and macros, for example:
</p>

<pre>
    #define X 100

    #define perc(a,b) ((a) * 100.0 / (b))
</pre>

<p>
The Java equivalent of these definitions might look like this:
</p>

<pre>
    class Globals {
    
        // define private constructor so that no
        // objects of the Globals class can be created
    
        private Globals() {}
    
        // global constants
    
        public static final int X = 100;
        public static final int Y = 200;
    
        // global &quot;macro&quot;
    
        public static double perc(double a, double b) {
            return a * 100.0 / b;
        }
    }
    
    public class PPDemo1 {
        public static void main(String[] args) {
            double p = Globals.perc(57.2958, Globals.Y);
            System.out.println(&quot;p = &quot; + p);
        }
    }
</pre>

<p>
<code>Globals</code> is a class used to hold public constants and static 
methods. It's got a private constructor so that no instances of 
the <code>Globals</code> class can be created. In other words, <code>Globals</code> is 
a packaging vehicle rather than a conventional class from which 
you create objects. Note that in this example there are other 
ways to define a group of constants. For example, you could use 
an enum pattern. In general, you should define constants in as 
local of a context as possible. You should also make constants 
private if possible. This example assumes that you do, in fact, 
need to define some constants that are pervasive across your 
program.
</p>

<p>
This Java language approach illustrated in the <code>Globals</code> class 
tends to work better for defining globals than the C/C++ approach
that uses the <code>#define</code> directive. For example, if you have some 
code like this:
</p>

<pre>
    #define X 100

    ...

    #define X 150
</pre>

<p>
various C++ compilers will produce a warning message. However,
this usage is probably an outright error, typically triggered by
defining the same constant with different values across multiple
header files. 
</p>

<p>
Note in this example that static methods have guaranteed function 
semantics. For example, method arguments are evaluated only once.
Macros fall short in this regard.
</p>

<p>
One issue with this example is whether the <code>perc</code> method is inlined 
(for performance). If you use the C/C++ preprocessor, and write 
a macro as illustrated in the C/C++ example, the macro will be 
expanded textually, and by definition is inline. There's no 
direct Java equivalent to this textual expansion. However, it's
usually possible to achieve the same end by doing the following 
in some combination: making methods final (static methods are 
implicitly final), turning on compiler optimization (<code>javac -O</code>), 
and using Java Virtual Machines that do dynamic method inlining. 
Understand that expanding a macro inline is not always a good 
thing -- it makes debugging difficult or impossible.
</p>

<p>
Another area to look at is modifying the operation of a program 
by the use of compiler or run time directives. For example, if 
a C program is compiled like this:
</p>

<pre>
    $ cc -DABC file.c
</pre>

<p>
and <code>file.c</code> has in it the preprocessor directive:
</p>

<pre>
    #ifdef ABC
    ...
    #endif
</pre>

<p>
the behavior of the program is modified based on the presence of 
<code>-DABC</code> on the compile line. The code in the <code>#ifdef ... #endif</code> 
block is compiled only if <code>-DABC</code> is specified.
</p>

<p>
This approach is also useful with Java programs, although there 
is less need for it. One classic use of <code>-D</code> directives is 
targeting an application for particular hardware and software 
architectures. The Java system partially solves this problem by 
offering a uniform abstraction, no matter what the underlying 
hardware and operating system. For example, a long data type is 
64 bits in the Java language. The size is independent of the
hardware you use.
</p>

<p>
The following code illustrates what is sometimes called 
&quot;conditional compilation&quot;:
</p>

<pre>
    class Debug {
        public static final boolean DEBUG = false;
    }
    
    public class PPDemo2 {
        public static void main(String[] args) {
            if (Debug.DEBUG) {
                System.out.println(&quot;DEBUG is true&quot;);
            }
        }
    }
</pre>

<p>
Here you have a &quot;global&quot; boolean variable <code>Debug.DEBUG</code>, and the 
execution of the code is dependent on the value of that variable. 
This usage takes advantage of a specific feature of the Java 
language specification that says:
</p>

<pre>
    int x = 0;

    while (false)
        x = 3;
</pre>

<p>
is illegal (&quot;<code>x = 3</code>&quot; is not reachable), but:
</p>

<pre>
    int x = 0;

    if (false)
        x = 3;
</pre>

<p>
is legal.
</p>

<p>
Note that a compiler can throw away the block of code inside of 
&quot;<code>if(Debug.DEBUG)</code>&quot; if the value is false, and <code>javac 1.4</code> does 
exactly that. If you say:
</p>

<pre>
    $ javap -c -classpath . PPDemo2
</pre>

<p>
the result is:
</p>

<pre>
    Compiled from PPDemo2.java
    public class PPDemo2 extends java.lang.Object {
        public PPDemo2();
        public static void main(java.lang.String[]);
    }
    
    Method PPDemo2()
        0 aload_0
        1 invokespecial #1 &lt;Method java.lang.Object()&gt;
        4 return
    
    Method void main(java.lang.String[])
        0 return
</pre>

<p>
Notice that there's no trace of the <code>System.out.println</code> method call.
</p>

<p>
You can also use the Java launcher and libraries to specify the
value of a system property. You can then use this value to modify 
the logic of your application. Here's an example:
</p>

<pre>
    public class PPDemo3 {
        public static void main(String[] args) {
            String prop = System.getProperty(
                &quot;property1&quot;);

            if (prop.equals(&quot;123&quot;)) {
                System.out.println(&quot;property1 is 123&quot;);
            }
        }
    }
</pre>

<p>
If you compile this code, and then say:
</p>

<pre>
    $ java -Dproperty1=123 PPDemo3
</pre>

<p>
the effect will be to set the value of the system property for use
within the program, that is:
</p>

<pre>
    property1 is 123
</pre>

<p>
Assertions are another area where you might want to alter the
behavior of a program from outside. In C/C++, an assertion is 
specified by saying:
</p>

<pre>
    assert(x &gt;= 100);
</pre>

<p>
<code>assert</code> is a macro, and its effect can be nullified using <code>-DNDEBUG</code>.
</p>

<p>
The Java language uses the assert keyword to specify assertions. Here's an example:
</p>

<pre>
    public class PPDemo4 {
        static void f(int i) {
            assert i &gt;= 0;
    
            // ... do other processing ...
        }
    
        public static void main(String[] args) {
            try {
                f(-1);
            }
            catch (AssertionError e) {
                System.err.println(
                    &quot;*** assertion failed ***&quot;);
            }
        }
    }
</pre>

<p>
You need to compile this code with:
</p>

<pre>
    $ javac -source 1.4 PPDemo4.java
</pre>

<p>
and then run it by saying:
</p>

<pre>
    $ java -ea PPDemo4
</pre>

<p>
You should see the following result:
</p>

<pre>
    *** assertion failed ***
</pre>

<p>
Normally you wouldn't catch an <code>AssertionError</code>. It's done in this 
example for demonstration purposes.    
</p>

<p>
If you don't specify <code>-ea</code> to the Java launcher, assertions are not
checked -- the assertions remain in your code and are ignored.
</p>

<p>
For more information about Java language approaches to 
preprocessing, see section 1.4,  Named Constants, section 13.2, 
Type Imports, and section 18.1.2, System Properties, in 
&quot;<a href="http://bulkmail2.sun.com/CTServlet?id=1049817986366">The Java 
Programming Language Third Edition</a>&quot; by Arnold, Gosling, and 
Holmes. Also see section 14.20, &quot;Unreachable Statements&quot; in &quot;<a href="http://bulkmail2.sun.com/CTServlet?id=1049817986379">The 
Java Language Specification Second Edition</a>&quot; by Gosling, Joy, 
Steele, and Bracha. 
And see item 21 &quot;Replace enum constructs with classes&quot; in 
&quot;<a href="http://bulkmail2.sun.com/CTServlet?id=1049817986392">Effective Java Programming Language Guide</a>&quot; by Joshua Bloch.
</p>

<table width="100%" border="0" cellspacing="0" cellpadding="0" align="center">

<tr>
<td>
<div align="right">
<a href="#top">back to top<img src="http://developer.java.sun.com/images/back_to_top.gif" border="0" alt="image"></a>
</div>
</td></tr>

<tr><td bgcolor="#ffffff" height="2"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" alt="." border="0"></td></tr>

<!-- Grey Horizontal Line Begins Here -->

<tr>
<td bgcolor="#cccccc" height="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" alt="." border="0"></td>
</tr>
</table> 

<!-- Grey Horizontal Line ends Here -->

<form method="POST" action="http://developer.java.sun.com/servlet/jdc.survey.TabulationServlet">
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr><td bgcolor="#ffffff" height="2"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" alt="." border="0"></td></tr>

<tr><td>
<h3>Reader Feedback</h3> 

<input type="hidden" name="survey_id" value="2600">
<input type="hidden" name="anonymous" value="True">
<input type="hidden" name="answer_count" value="3">
<input type="hidden" name="answer1" value="AprCore_tt040803">
<input name="answer2" type="radio" value="2">&nbsp; Very worth reading&nbsp; 
<input name="answer2" type="radio" value="1">&nbsp; Worth reading&nbsp; 
<input name="answer2" type="radio" value="0">&nbsp; Not worth reading&nbsp; 
 
<p>
If you have other comments or ideas for future technical tips, please type them  here: 
</p>
 
<p>
<textarea name="answer3" rows="6" cols="50"></textarea> 
</p>
 
<p>
<input type="Submit" value="Submit"> &nbsp; <input type="Reset"> 
</p>

<p> 
Have a question about Java programming? Use  
<a href="http://bulkmail2.sun.com/CTServlet?id=1049817986451">Java Online Support.</a> 
</p>

</td></tr></table>
</form> 

<table width="100%" border="0" cellspacing="0" cellpadding="0" align="center">
<tr>
<td>
<div align="right">
<a href="#top">back to top<img src="http://developer.java.sun.com/images/back_to_top.gif" border="0" alt="image"></a>
</div>
</td></tr>

<tr><td bgcolor="#ffffff" height="2"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" alt="." border="0"></td></tr>

<!-- Grey Horizontal Line Begins Here -->

<tr>
<td bgcolor="#cccccc" height="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" alt="." border="0"></td>
</tr>
</table> 

<!-- Grey Horizontal Line ends Here -->

<br>

<span class="small">IMPORTANT: Please read our Terms of Use, Privacy, and Licensing policies:<br>
<a href="http://www.sun.com/share/text/termsofuse.html"><span class="link">http://www.sun.com/share/text/termsofuse.html</span></a><br>
<a href="http://www.sun.com/privacy/"><span class="link">http://www.sun.com/privacy/</span></a><br> 
<a href="http://developer.java.sun.com/berkeley_license.html"><span class="link">http://developer.java.sun.com/berkeley_license.html</span></a>
</span><br><br>

<span class="small">
Comments? Send your feedback on the Core Java Technologies Tech Tips to: <a href="mailto:jdc-webmaster@sun.com"><span class="link">jdc-webmaster@sun.com</span></a>
</span><br><br>

<span class="small">
Subscribe to other Java developer Tech Tips:
</span><br><br>

<span class="small">
- Enterprise Java Technologies Tech Tips. Get tips on using enterprise Java technologies and APIs, such as those in the Java 2 Platform, Enterprise Edition (J2EE).<br>
- Wireless Developer Tech Tips. Get tips on using wireless Java technologies and APIs, such as those in the Java 2 Platform, Micro Edition (J2ME).<br><br>
</span>
   
<span class="small">
To subscribe to these and other JDC publications:<br>
- Go to the JDC Newsletters and Publications page, choose the newsletters you want to <a href="http://bulkmail2.sun.com/CTServlet?id=1049817986405"><span class="link">subscribe</span></a> to and click &quot;Update&quot;.<br>
  - To unsubscribe, go to the <a href="http://bulkmail2.sun.com/CTServlet?id=1049817986405"><span class="link">subscriptions page</span></a>, uncheck the appropriate checkbox, and click &quot;Update&quot;.
</span><br><br>

<span class="small">ARCHIVES: You'll find the Core Java Technologies Tech Tips archives at:<br>
<a href="http://bulkmail2.sun.com/CTServlet?id=1049817986464"><span class="link">http://java.sun.com/jdc/TechTips/</span></a>
</span><br><br>

<span class="small">Copyright 2003 <a href="http://bulkmail2.sun.com/CTServlet?id=1049817986481"><span class="link">Sun Microsystems, Inc.</span></a> All rights reserved.<br>
4150 Network Circle, Santa Clara, CA 95054 USA.
</span><br><br>

<span class="small">This document is protected by copyright. For more information, see:
<br><a href="http://java.sun.com/jdc/copyright.html"><span class="link">http://java.sun.com/jdc/copyright.html</span></a>
</span><br><br>

<span class="small">Trademark Information: <a href="http://www.sun.com/suntrademarks/"><span class="link">http://www.sun.com/suntrademarks/</span></a><br>
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.</span><br><br>

<a name="JVM"></a>
<span class="small">* As used in this document, the terms &quot;Java virtual machine&quot; 
  or "JVM" mean a virtual machine for the Java platform.</span><br><br>

<!-- ================ -->
<!-- End Main Content -->
<!-- ================ -->

<center>
<a href="http://bulkmail2.sun.com/CTServlet?id=1049817986481"><img src="http://developer.java.sun.com/images/lgsun.gif" border="0" alt="Sun Microsystems, Inc."></a>
</center>

</td>
</tr>
</table>

</td></tr>
</table>
</td>

<td bgcolor="#cccccc" width="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" border="0" alt="."></td>
</tr>
<tr>
<td colspan="3" bgcolor="#cccccc" width="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" border="0" alt="."></td>
</tr>
</table>

<table bgcolor = "#efefef"><tr><td><a href="http://subscriptions.sun.com/unsubscribe?33208391174049728">Please unsubscribe me from this newsletter.</a><img src="http://bulkmail2.sun.com/OTServlet?id=33208391174049728" width=1 height=1></td></tr></table></body>
</html>

