Figure 1   StackTrace.java

/////////////////////////////////////////////////////////////////
// StackTrace.java

import java.io.*;

/**
 * Demonstrates how to get a stack trace as a String
 * @author Jonathan Locke
 */
public class StackTrace
{
    /**
     * Returns a stack trace for the calling thread
     * @return Stack trace of calling thread as a String.
     */
    public static String getStackTrace()
    {
        CharArrayWriter c = new CharArrayWriter();
        new Exception("Test").printStackTrace(new PrintWriter(c));
        return c.toString();
    }

    /**
     * Main application entrypoint.
     * @param arg Command line arguments
     */
    static public void main(String[] arg)
    {
        System.out.println(getStackTrace());
    }
}


Figure 2   Traversing a Directory Tree

Walk.java

/////////////////////////////////////////////////////////////////
//
// Walk.java
//

import java.io.*;

/**
 * Walks a directory tree making callbacks to a WalkObserver 
 * @author Jonathan Locke
 */
public class Walk
{
    /**
     * Walks a directory tree, calling the WalkObserver at each file.
     * @param rootDirectory Root of directory tree to walk
     * @param o The directory WalkObserver object for callbacks
     * @param indentLevel The current level of recursion
     */
    static void walk(File rootDirectory, WalkObserver o, int indentLevel)
    {
        // Get list of files in directory
        String[] file = rootDirectory.list();

        // Traverse files
        for (int i = 0; i < file.length; i++)
        {
            // Call observer callback with file
            File f = new File(rootDirectory, file[i]);
            o.at(f, indentLevel);

            // If the file is a directory, recurse into it
            if (f.isDirectory())
            {
                walk(f, o, indentLevel + 1);
            }
        }
    }
}
WalkObserver.java
/////////////////////////////////////////////////////////////////
//
// WalkObserver.java
//

import java.io.*;

/**
 * Interface for objects that want to observe directory traversals.
 * @author Jonathan Locke
 */
public interface WalkObserver
{
    /**
     * The WalkObserver entrypoint.  Shows each file in a tree traversal.
     * @param f File encountered
     * @param indentLevel Level of recursion
     */
    public void at(File f, int indentLevel);
}


Figure 3   FinalizeMe.java


 /////////////////////////////////////////////////////////////////
 //
 // FinalizeMe.java
 //
 
 /**
  * A test program to demonstrate finalization
  * @author Jonathan Locke
  */
 public class FinalizeMe
 {
     /**
      * Called after object becomes unreachable, but before
      * garbage collection of the object
      */
     protected void finalize() throws Throwable
     {
         super.finalize();
         System.out.println("In finalizer!");
     }
     
     /**
      * Main application entrypoint.
      * @param arg Command line arguments
      */
     static public void main(String[] arg)
     {
         // Create a FinalizeMe object
         FinalizeMe f = new FinalizeMe();
 
         // Force a garbage collection
         System.out.println("First gc");
         System.gc();
         System.runFinalization();
 
         // Get rid of last reference to object
         f = null;
 
         // Force a garbage collection
         System.out.println("Second gc");
         System.gc();
         System.runFinalization();
         System.out.println("Done.");
     }
 }


Figure 4   Deadlock.java


 /////////////////////////////////////////////////////////////////
 //
 // Deadlock.java
 //
 
 /**
 A demonstration of deadlocking in Java.
  * @author Jonathan Locke
  */
 public class Deadlock implements Runnable
 {
     Object ready = new Object();      // Main referee thread waits on this object
                                       // for both threads to get ready
     Object go = new Object();         // The wantsSalt and wantsPepper threads wait
                                       // on this until the referee says "go!"
     Object salt = new Object();       // The salt object
     Object pepper = new Object();     // The pepper object
 
     /**
      * The wantsSalt thread's agenda
      */
     void wantsSalt()
     {
         synchronized (pepper)
         {
             System.out.println("wantsSalt: I've got the pepper and I'm ready to go.");
             synchronized(ready)
             {
                 ready.notifyAll();
             }
             try
             {
                 synchronized(go)
                 {
                     go.wait();
                 }
             }
             catch (InterruptedException e)
             {
             }
             
             System.out.println("wantsSalt: If you first give the salt, then I'll
                                 give you the pepper.");
             System.out.println("wantsSalt: Waiting for the salt.");
 
             synchronized (salt)
             {
                 Object o = salt;
                 System.out.println("wantsSalt: Thanks, I've got exclusive access to
                                     the salt now.");
             }
         }
         System.out.println("wantsSalt: You can now have the pepper.");
     }
 
     /**
      * The wantsPepper thread's agenda
      */
     void wantsPepper()
     {
         synchronized (salt)
         {
             System.out.println("wantsPepper: I've got the salt and I'm ready to go.");
             synchronized(ready)
             {
                 ready.notifyAll();
             }
             try
             {
                 synchronized(go)
                 {
                     go.wait();
                 }
             }
             catch (InterruptedException e)
             {
             }
 
             System.out.println("wantsPepper: If you first give me the pepper, then
                                 I'll give you the salt.");
             System.out.println("wantsPepper: Waiting for the pepper.");
 
             synchronized (pepper)
             {
                 Object o = pepper;
                 System.out.println("wantsPepper: Thanks, I've got exclusive access
                                     to the pepper now.");
             }
             System.out.println("");
         }       
         System.out.println("wantsPepper: You can now have the salt.");
     }
 
     /**
      * Entrypoint for threads.
      */
     public void run()
     {
         if (Thread.currentThread().getName().equals("wantsSalt"))
         {
             wantsSalt();
         }
         else
         {            
             wantsPepper();
         }
     }
 
     /**
      * Constructor
      */
     public Deadlock()
     {
         synchronized(ready)
         {
             new Thread(this, "wantsSalt").start();
             new Thread(this, "wantsPepper").start();
 
             try
             {
                 System.out.println("referee: Waiting for first thread");
                 ready.wait();
                 System.out.println("referee: Waiting for second thread");
                 ready.wait();
             }
             catch (InterruptedException e)
             {
             }
         }
         synchronized(go)
         {
             System.out.println("referee: Now you may begin!!");
             go.notifyAll();
         }
     }
     
     /**
      * Main application entrypoint.
      * @param arg Command line arguments
      */
     static public void main(String[] arg)
     {
         new Deadlock();
     }
}