Return-Path: <env_40341097-60885932@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; Thu, 21 Aug 2003 03:06:58 -0400
X-Sieve: CMU Sieve 2.2
Received: from fort-point-station.mit.edu by po10.mit.edu (8.12.4/4.7) id h7L76ubU008665; Thu, 21 Aug 2003 03:06:56 -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 h7L76tmM003943
	for <alexp@mit.edu>; Thu, 21 Aug 2003 03:06:55 -0400 (EDT)
Date: 21 Aug 2003 00:00:35 -0800
From: "SDN - Core Java Technologies Tech Tips" <sunmail@hermes.sun.com>
To: alexp@mit.edu
Message-Id: <40341097-60885932@hermes.sun.com>
Subject: Core Java Technologies Tech Tips, August, 19, 2003 (Formatting Messages, Unloading/Reloading Classes)
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.2
X-Spam-Level: ** (2.2)
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=40341097-60885932:1061310102588"><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=40341097-60885932:1061310102600" style="text-decoration:none;">View this issue as simple text</a></td>
<td align="right" height="20"><span class="purple">August 19, 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, August 19, 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="-">Formatting Messages With Variable Content</a><br>    
<a href="#2"><img src="http://developer.java.sun.com/images/anchor.gif" border="0" alt="-">Unloading and Reloading Classes</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 John Zukowski, president of <a href="http://www.jzventures.com">JZ Ventures, Inc.</a>
</p>

<p>
See the Subscribe/Unsubscribe note at the end of this newsletter to subscribe to Tech Tips that focus on technologies and products in other Java platforms.
</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>FORMATTING MESSAGES WITH VARIABLE CONTENT</h3>

<p>
Internationalization is the process of designing an application to work with multiple languages and in regions around the world. This not only involves translating text labels to other languages. It also also means displaying information such as dates and times in a format appropriate for that particular region of the globe.
</p>

<p>
The first step involved in internationalizing text labels and messages is to move everything into resource bundles. For each quoted string you want the user to see, you create an entry in a resource bundle. Then, you change the code to dynamically look up the text label or message based on the locale of the user. When you do this correctly, a user in the United States might see Help as the label for a help menu, while a Spanish user would see Ayuda.
</p>

<p>
This technique works perfectly well for straight text-to-text translations, where you are always displaying a &quot;whole&quot; message. However this technique doesn't work for compound messages, where you need to combine several pieces of a message into one longer message. For instance, consider the following message:
</p>

<pre>
   Hello, John. Good luck.
</pre>

<p>
You might think that you could simply use string concatenation, and build the compound message by appending multiple strings together:
</p>

<pre>
   System.out.println(
     &quot;Hello, &quot; +
     name +
     &quot;. Good luck.&quot;)
</pre>

<p>
You might also assume that you could localize the compound message by moving the <code>Hello</code> and <code>Good luck</code> strings into resource bundles. This might work, but what happens when you get to a language where the form of the greeting becomes something like:
</p>

<pre>
   Hello and good luck, John.
</pre>

<p>
You could break up the resource bundle strings into a prefix part before the name, and a suffix part after the name. But this complicates things for translators because they must know what pieces go together. A better approach is to have one text string, with a variable holder in the middle for the name.
</p>

<p>
For English, that string might be:
</p>

<pre>
   Hello, {0}. Good luck.
</pre>

<p>
Seeing that whole string, a translator for Spanish might realize it is better to put hello and good luck together, as follows:
</p>

<pre>
   Hola y buena suerte, {0}.
</pre>

<p>
When it's time to actually display the message, the <code>MessageFormat</code> class of the <code>java.text</code> package can be used to replace the variables. <code>MessageFormat</code> takes a set of objects, formats them, and inserts the formatted strings into a pattern. The pattern could be something like &quot;<code>Hello, {0}. Good luck.</code>&quot; 
</p>

<p>
To use <code>MessageFormat</code>, you start by creating a formatter:
</p>

<pre>
   String pattern = ...; // from bundle
   Locale aLocale = ...; // the Locale

   MessageFormat formatter = new MessageFormat(pattern);
   formatter.setLocale(aLocale);
</pre>

<p>
For each pattern, you could create different <code>MessageFormat</code> objects. However you can also reuse the <code>MessageFormat</code> object with another pattern by calling the <code>applyPattern</code> method with the new pattern template. Remember to do this after changing locales:
</p>

<pre>
   formatter.setLocale(aNewLocale);
   formatter.applyPattern(aPatternForNewLocale);
</pre>

<p>
After you have the formatter, you need to generate the output message. To do this, you pass in an array of arguments, where each {#} in the pattern is replaced, based on its index in the array. For instance, a one element array is needed for the pattern &quot;<code>Hello, {0}. Good luck.</code>&quot; The one element in the array contains the text that will be inserted at position 0 in the string. Here's an example -- it's a one element array that contains the string &quot;<code>John</code>&quot; for insertion into the previous pattern:
</p>

<pre>
  Object messageArgs[] = {&quot;John&quot;};
</pre>

<p>
To generate the output, you call the format method of <code>MessageFormat</code>, specifying the message arguments:
</p>

<pre>
   System.out.println(formatter.format(messageArgs));
</pre>

<p>
The following program, <code>HelloGoodLuck</code>, demonstrates the use of <code>MessageFormat</code>. To keep things simple, the program doesn't use resource bundles:
</p>

<pre>
   import java.text.*;
   import java.util.*;

   public class HelloGoodLuck {
     public static void main(String args[]) {
       String pattern = &quot;Hello, {0}. Good luck.&quot;;
       Locale aLocale = Locale.US;
       MessageFormat formatter = new MessageFormat(
                                   pattern, aLocale);
       Object messageArgs[] = {&quot;John&quot;};
       System.out.println(
                        formatter.format(messageArgs));
       // Pass in command line args
       if (args.length != 0) {
         System.out.println(formatter.format(args));
       }
     }
   }
</pre>

<p>   
The <code>HelloGoodLuck</code> program produces a second message if you pass in a name on the command line. If you run the program with the following command:
</p>

<pre>
   java HelloGoodLuck Spot
</pre>

<p>
You should see the output:
</p>

<pre>
   Hello, John. Good luck.
   Hello, Spot. Good luck.
</pre>

<p>
Using <code>MessageFormat</code> is not limited to text substitution. You can also use it to format numbers and dates, that is, without having to use the <code>NumberFormat</code> and <code>DateFormat</code> classes. The <a href="http://bulkmail2.sun.com/CTServlet?id=40341097-60885932:1061310102461">javadoc</a> for the <code>MessageFormat</code> class describes all the support available. 
</p>

<p>
After the argument index part of <code>{#}</code>, you can specify a format type and a style (separated by commas). For instance, in the case of a date, you can specify a short, medium, long, or full to map to the <code>DateFormat</code> constants. If the argument type is a <code>Date</code>, and the <code>MessageFormat</code> maps that argument to &quot;<code>{1,date,long}</code>&quot;, you would see the long format for a date displayed (in a format appropriate for the locale). You can also display dates with a &quot;time&quot; type, using the same short, medium, long, full options. For a number, the available styles include integer, currency, and percent. If you don't like the built-in styles, and know the pattern strings of <code>SimpleDateFormat</code> and <code>DecimalFormat</code>, you can also specify those directly.
</p>

<p>
To demonstrate, the following <code>MessageFormat</code> pattern uses time, date, and number:
</p>

<pre>
   At the tone, the time is now {0, time, short} 
   on {0, date, long}. 
   You now owe us {1, number, currency}.
</pre>

<p>
If you then provided a <code>Date</code> and <code>Number</code> as the input argument, it would generate output for US-English and German locales.
</p>

<p>
<img src="http://developer.java.sun.com/developer/JDCTechTips/images/tt081903_ExtendedFormat.gif" width="500" height="100" border="0" alt="ExtendedFormat">
</p>

<p>
And here is the program that produces that output. To keep the demonstration simple, resource bundles were not used. However, the strings in the <code>pattern</code> and <code>germanPattern</code> variables in the program should be located in resource bundles.
</p>

<pre>
   import java.text.*;
   import java.util.*;
   import java.io.*;
   import java.awt.*;
   import javax.swing.*;

   public class ExtendedFormat {
     public static void main(String args[]) {
       String pattern = 
         &quot;At the tone, the time is now {0, time, short}&quot; + 
         &quot; on {0, date, long}.&quot; +
         &quot; You now owe us {1, number, currency}.&quot;;
       String germanPattern =
         &quot;Beim Zeitton ist es {0, time, short} Uhr&quot; +
         &quot; am {0, date, long}.&quot; +
         &quot; Sie schulden uns jetzt {1, number, currency}.&quot;;
       
       StringWriter sw = new StringWriter(100);
       PrintWriter out = new PrintWriter(sw, true);
       MessageFormat formatter = 
                 new MessageFormat(pattern, Locale.US);
       Object messageArgs[] = 
                     {new Date(), new Double(9000.12)};
       out.println(formatter.format(messageArgs));
       formatter.setLocale(Locale.GERMAN);
       // Need to reset pattern after changing locales
       formatter.applyPattern(germanPattern);
       out.println(formatter.format(messageArgs));
       out.close();
       // Put output in window
       JFrame frame = new JFrame(&quot;Extended Format&quot;);
       frame.setDefaultCloseOperation(
                                 JFrame.EXIT_ON_CLOSE);
       JTextArea ta = new JTextArea(sw.toString());
       JScrollPane pane = new JScrollPane(ta);
       frame.getContentPane().add(
                            pane, BorderLayout.CENTER);
       frame.setSize(500, 100);
       frame.show();
     }
   }
</pre>

<p>
There is much more to properly internationalizing your applications than using <code>MessageFormat</code>. For more information on the use of resource bundles (where all these string patterns should come from), see the May 21, 1998 Tech Tip, &quot;<a href="http://bulkmail2.sun.com/CTServlet?id=40341097-60885932:1061310102480">Resource Bundles</a>&quot;. Also, for more information on formatting date and time strings, see the June 24, 2003 Tech Tip, &quot;<a href="http://bulkmail2.sun.com/CTServlet?id=40341097-60885932:1061310102500">Internationalizing Dates, Times, Months, and Days of the Week</a>&quot;.
</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>UNLOADING AND RELOADING CLASSES</h3>

<p>
The July 22, 2003 Tech Tip titled &quot;<a href="http://bulkmail2.sun.com/CTServlet?id=40341097-60885932:1061310102516">Compiling Source Directly From a Program</a>&quot; offered a way to compile source files directly from your Java program. It presented a simple editor in which you can name a class and provide the source. That approach works fine, provided the class is not one that you already compiled and loaded during the current execution run. If indeed you previously compiled and loaded the class, you can't then edit it and recompile it using the approach covered in the previous Tech Tip. The issue here is the underlying class loader. All classes loaded through the system class loader will never be unloaded. To allow the program to let you reedit the source for a class, and then recompile and reload it, you need to work with a different class loader. In this tip, you'll learn how to create a custom class loader, one that lets you load your newly compiled class (or any c!
 lass). You'll also learn how to discard the class such that the next time you compile the class, the newly compiled class is loaded.
</p>

<p>
An instance of the <code>ClassLoader</code> class of the <code>java.lang</code> package is responsible for loading all classes. For system classes, that class loader is available through the <code>getSystemClassLoader</code> method of <code>ClassLoader</code>. For user classes, if that class is already loaded, you can ask for the <code>ClassLoader</code> with the <code>getClassLoader</code> method of <code>Class</code>.
</p>

<p>
In the <code>RunIt</code> program from the earlier Tech Tip, the <code>forName</code> method of <code>Class</code> was used to load the class data (that is, to get an instance of <code>Class</code>). If you want to use a different class loader, you have to use the <code>loadClass</code> method of <code>ClassLoader</code> to load the class data. In other words, you need to code this:
</p>

<pre>
   String className = ...;
   Class aClass = loader.loadClass(className);   
</pre>

<p>
instead of this:
</p>

<pre>
   String className = ...;
   Class aClass = Class.forName(className);   
</pre>

<p>   
Functionally, the two code blocks above are identical when loading through the same class loader. The first block loads the class through the same loader as where the code is found. The second loads the class through the class loader specified by the loader variable. In both cases, you would then call something like <code>newInstance</code> to create an instance of the class.
</p>

<p>
Repeated calls to <code>Class.forName</code> load the same class (assuming the class loader of the calling class doesn't change). Repeated calls to <code>loader.loadClass</code> load the same class. However, the second block allows you to reload a class. To do that, you create a new <code>ClassLoader</code>:
</p>

<pre>
   String className = ...;
   // create new loader instance
   ClassLoader loader = ...; 
   Class aClass = loader.loadClass(className);
</pre>

<p>
In this particular code block, a new loader is created between calls to <code>loadClass</code>. If the class definition for <code>className</code> changes between calls, the new version of the class is loaded the second time through.
</p>

<p>
If you change the <code>RunIt</code> program to use this mechanism, you can edit the source after compiling and running the program. The program should generate output appropriate to the new source, not the old.
</p>

<p>
The only thing left is where to get the <code>ClassLoader</code>. The <code>ClassLoader</code> class is itself an abstract class. Predefined loaders include the <code>SecureClassLoader</code> of <code>java.security</code>, which adds permission support, and the <code>URLClassLoader</code> of <code>java.net</code>. Of the two predefined loaders, only <code>URLClassLoader</code> offers support for public construction through either its constructors or static <code>newInstance</code> methods. See the <a href="http://bulkmail2.sun.com/CTServlet?id=40341097-60885932:1061310102531">documentation</a> for <code>URLClassLoader</code> for further details.
</p>

<p>
Creating a <code>URLClassLoader</code> involves creating an array of <code>URL</code> objects. These <code>URL</code> objects serve as the locations that the custom class loader uses to find classes. You specify the elements of the array similarly to the way you specify path elements for the <code>CLASSPATH</code> environment variable, where the path elements are separated by a <code>;</code> on Windows and a <code>:</code> on Unix machines. Each element in the URL array can be a located locally or on a remote host. Anything ending in a &quot;<code>/</code>&quot; is presumed to be a directory. Anything else is presumed to be a JAR file.
</p>

<p>
For instance, if you want to create a <code>ClassLoader</code> that works like the default classpath, that is, only searching in the current directory, you can code the following:
</p>

<pre>
   File file = new File(&quot;.&quot;);
   ClassLoader loader = new URLClassLoader(
     new URL[] {file.toURL()}
   );
</pre>

<p>
The first line creates a <code>File</code> object, referencing the current directory. The second line calls the <code>URLClassLoader</code> constructor. Passed into the constructor is an array of one <code>URL</code> object: the <code>URL</code> to the <code>File</code>.
</p>

<p>
If you change the <code>RunIt</code> program to include the following code, recompile it, and run it, the program will discard the loaded classes between runs and reload them. Notice that unlike the <code>RunIt</code> program in the earlier Tech Tip, the following code does not create an instance of the class to invoke the <code>main</code> method. There is no need to create an instance of the class because the <code>main</code> method is static, 
</p>

<pre>
   // Create new class loader 
   // with current dir as CLASSPATH
   File file = new File(&quot;.&quot;);
   ClassLoader loader = new URLClassLoader(
     new URL[] {file.toURL()}
   );
   // load class through new loader
   Class aClass = loader.loadClass(className.getText());
   // run it
   Object objectParameters[] = {new String[]{}};
   Class classParameters[] =
     {objectParameters[0].getClass()};
   Method theMethod = aClass.getDeclaredMethod(
     &quot;main&quot;, classParameters);
   // Static method, no instance needed
   theMethod.invoke(null, objectParameters);
</pre>

<p> 
Here's the complete code example, with the <code>RunIt</code> program renamed to <code>RunItReload</code>.
</p>

<pre>
   import java.awt.*;
   import java.awt.event.*;
   import javax.swing.*;
   import java.io.*;
   import java.net.*;
   import java.lang.reflect.*;

   public class RunItReload extends JFrame {
     JPanel contentPane;
     JScrollPane jScrollPane1 = new JScrollPane();
     JTextArea source = new JTextArea();
     JPanel jPanel1 = new JPanel();
     JLabel classNameLabel = new JLabel(&quot;Class Name&quot;);
     GridLayout gridLayout1 = new GridLayout(2,1);
     JTextField className = new JTextField();
     JButton compile = new JButton(&quot;Go&quot;);
     Font boldFont = new java.awt.Font(
                                  &quot;SansSerif&quot;, 1, 11);

     public RunItReload() {
       super(&quot;Editor&quot;);
       setDefaultCloseOperation(EXIT_ON_CLOSE);
       contentPane = (JPanel) this.getContentPane();
       this.setSize(400, 300);
       classNameLabel.setFont(boldFont);
       jPanel1.setLayout(gridLayout1);
       compile.setFont(boldFont);
       compile.setForeground(Color.black);
       compile.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
           try {
             doCompile();
           } catch (Exception ex) {
             System.err.println(
                   &quot;Error during save/compile: &quot; + ex);
             ex.printStackTrace();
           }
         }
       });
       contentPane.add(
                    jScrollPane1, BorderLayout.CENTER);
       contentPane.add(jPanel1, BorderLayout.NORTH);
       jPanel1.add(classNameLabel);
       jPanel1.add(className);
       jScrollPane1.getViewport().add(source);
       contentPane.add(compile, BorderLayout.SOUTH);
     }
     public static void main(String[] args) {
       Frame frame = new RunItReload();
       // Center screen
       Dimension screenSize =
         Toolkit.getDefaultToolkit().getScreenSize();
       Dimension frameSize = frame.getSize();
       if (frameSize.height &gt; screenSize.height) {
         frameSize.height = screenSize.height;
       }
       if (frameSize.width &gt; screenSize.width) {
         frameSize.width = screenSize.width;
       }
       frame.setLocation(
         (screenSize.width - frameSize.width) / 2,
         (screenSize.height - frameSize.height) / 2);
       frame.show();
     }
     private void doCompile() throws Exception {
       // write source to file
       String sourceFile = className.getText() + &quot;.java&quot;;
       FileWriter fw = new FileWriter(sourceFile);
       fw.write(source.getText());
       fw.close();
       // compile it
       int compileReturnCode =
         com.sun.tools.javac.Main.compile(
             new String[] {sourceFile});
       if (compileReturnCode == 0) {
         // Create new class loader 
         // with current dir as CLASSPATH
         File file = new File(&quot;.&quot;);
         ClassLoader loader = 
         new URLClassLoader(new URL[] {file.toURL()});
         // load class through new loader
         Class aClass = loader.loadClass(
                                  className.getText());
         // run it
         Object objectParameters[] = {new String[]{}};
         Class classParameters[] =
                     {objectParameters[0].getClass()};
         Method theMethod = aClass.getDeclaredMethod(
                              &quot;main&quot;, classParameters);
         // Static method, no instance needed
         theMethod.invoke(null, objectParameters);
       }
     }
   }
</pre>

<p>
You need to compile and execute this program in a slightly different way than you did for the <code>RunIt</code> program in the earlier Tech Tip. Because the custom class loader is using the current directory as the place where reloadable classes need to come from, you can't load the actual <code>RunItReload</code> class from the same classpath. Otherwise, the system class loader will load the compiled class from the same location (and class loader). You need to tell the compiler to send the compiled classed for <code>RunItReload</code> to a different location. You run the program with that other location in the classpath, not with &quot;<code>.</code>&quot; in it. Remember that you need to include <code>tools.jar</code> in the classpath to compile. The following command sends the newly compiled <code>.class</code> files for <code>RunItReload</code> to the <code>XYZ</code> subdirectory. Feel free to pick a different subdirectory name. (Although the command is shown on multip!
 le lines it needs to go on one line):
</p>

<p>
In Windows: 
</p>

<pre>
    mkdir XYZ
    javac -d XYZ -classpath 
     c:\j2sdk1.4.2\lib\tools.jar RunItReload.java
</pre>

<p>
In Unix: 
</p>

<pre>
    mkdir XYZ
    javac -d XYZ -classpath 
     /homedir/jdk14/j2sdk1.4.2/lib/tools.jar 
     RunItReload.java
</pre>

<p>
Replace <code>homedir</code> with your actual home directory.
</p>

<p>
If you get an error that the system cannot find the path specified, be sure to create the <code>XYZ</code> directory before compilation.
</p>

<p>
As before, you need to include the tools.jar file in your runtime classpath, and you need to include the <code>XYZ</code> directory for the actual <code>RunItReload</code> program. To run the program, issue the following command. (Again, although the command is shown on multiple lines, it needs to go on one line). 
</p>

<p>
In Windows: 
</p>

<pre>
    java -classpath 
     c:\j2sdk1.4.2\lib\tools.jar;XYZ RunItReload
</pre>

<p>
In Unix: 
</p>

<pre>
   java -classpath 
      /homedir/jdk14/j2sdk1.4.2/lib/tools.jar:
      XYZ RunItReload
</pre>

<p>
The <code>XYZ</code> here is carried over from the prior <code>javac</code> step. The target directory for compilation (specified after <code>-d</code>) must match the runtime classpath.
</p>

<p>
Running the program displays the GUI. Then you can: 
</p>

<ol>
<li>Enter the name of the class, such as <code>Sample2</code>, to be compiled in the <code>JTextField</code>.</li>
<li>
Enter the source code in the <code>JTextArea</code>. Here's the source code for <code>Sample2</code>:
<pre>
    public class Sample2 {
      public static void main(String args[]) {
        System.out.println(new java.util.Date());
        // System.out.println(&quot;Hello, World!&quot;);
      }
    }
</pre>
</li>
<li>Click the Go button. </li>
</ol>

<p>
<img src="http://developer.java.sun.com/developer/JDCTechTips/images/tt081903_Sample2.gif" width="400" height="300" border="0" alt="Sample2">
</p>

<p>
Output is sent to the console. For example, <code>Sample2</code> should produce output that looks something like this: 
</p>

<pre>
  Tue Aug 19 11:25:16 PDT 2003
</pre>

<p>
Comment out the line that prints the date, and uncomment the line that prints &quot;<code>Hello World</code>&quot;. Click the Go button. You should now see the following in your console:
</p>

<pre>
  Hello, World!
</pre>

<p>
You see a different line displayed because a new class loader was created, one that unloaded previously loaded classes.
</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="AugCore_tt081903">
<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=40341097-60885932:1061310102611">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="http://developers.sun.com/contact/feedback.jsp?category=sdn"><span class="link">http://developers.sun.com/contact/feedback.jsp?category=sdn</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=40341097-60885932:1061310102559"><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=40341097-60885932:1061310102559"><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=40341097-60885932:1061310102630"><span class="link">http://java.sun.com/jdc/TechTips/index.html</span></a>
</span><br><br>

<span class="small">Copyright 2003 <a href="http://bulkmail2.sun.com/CTServlet?id=40341097-60885932:1061310102647"><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">Java, J2SE, J2EE, J2ME, and all Java-based marks are trademarks or registered trademarks (<a href="http://www.sun.com/suntrademarks/"><span class="link">http://www.sun.com/suntrademarks/</span></a>) of Sun Microsystems, Inc. in the United States and other countries.</span>
<br><br>

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

<center>
<a href="http://bulkmail2.sun.com/CTServlet?id=40341097-60885932:1061310102647"><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>

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


