//#
//# Java Memory Leak in java.util.concurrent package
//# $Revision: 1.1 $
//# Copyright 2004 by Eric Y. Theriault
//# All Rights Reserved.
//# http://www.eyt.ca/blog/item/119/
//#
package ca.eyt.tests;

/**
 * The code here demonstrates a memory leak in Java's java.util.concurrent
 * package from Java 1.5.  The issue is discussed in the following blog entry:
 * <a href="http://www.eyt.ca/blog/item/119/">http://www.eyt.ca/blog/item/119/</a>.
 *
 * @author Eric Y. Theriault <eric@eyt.ca>
 * @version 1.0
 */
public class ConcurrentMemoryLeak {
    /**
     * <p>The following code demonstrates the leak reported at
     * http://altair.cs.oswego.edu/pipermail/concurrency-interest/2005-January/001318.html
     * and confirmed in
     * http://altair.cs.oswego.edu/pipermail/concurrency-interest/2005-January/001319.html
     * by Doug Lea; the issue is discussed in Java Bug 6236036
     * (http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6236036), resolved in Mustang.</p>
     * <p>The following code will leak a java.util.concurrent.LinkedBlockingQueue$Node.
     * The leak only occurs when the code times out; in other cases, looking at jmap -histo,
     * you may think that it is leaking, but forcing a garbage collection will clean this
     * up.</p>
     */
    private void originallyReportedLeak() {
      java.util.concurrent.BlockingQueue bl = new java.util.concurrent.LinkedBlockingQueue( 2000 );
      while ( true ) {
         try {
            Object o = bl.poll( 2, java.util.concurrent.TimeUnit.MILLISECONDS );
            // do something with o
         } catch ( InterruptedException ie ) {
            // handle appropriately.
         }
      }
   }

   /**
    * <p>The following code also demonstrates a leak.</p>
    * <p>The following code will leak a java.util.concurrent.locks.AbstractQueuedSynchronizer$Node.</p>
    */
   private void anotherSimilarLeak() {
      java.util.concurrent.CountDownLatch latch = new java.util.concurrent.CountDownLatch( 1 );
      while ( true ) {
         try {
            latch.await( 2, java.util.concurrent.TimeUnit.MILLISECONDS );
            // do something since we had the condition
         } catch ( InterruptedException ie ) {
            // handle appropriately.
         }
      }
   }

   /**
    * Just a dummy main.  You will have to change the method name to call the
    * appropriate method above, since both methods are infinite loops.
    * @param args Ignored.
    */
   public static void main( String[] args ) {
      try {
         ConcurrentMemoryLeak cml = new ConcurrentMemoryLeak();
         cml.anotherSimilarLeak();
      } catch ( Throwable t ) {
         t.printStackTrace();
      }
   }
}

