import java.util.ArrayList;
import java.util.List;
import java.util.WeakHashMap;

/**
 *
You can think of direct references as strong references that require no
extra coding to create or access the object. The remaining three types
of references are subclasses of the Reference class found in the
java.lang.ref package.
  SoftReference - like data cache, Garbage collector arbitarily frees
     before throwing OutOfMemoryException
  WeakReference class - weaker than soft references. If the only references
     to an object are weak references, the garbage collector can reclaim the
     memory used by an object at any time. There is no requirement for a low
     memory situation. Typically, memory used by the object is reclaimed in
     the next pass of the garbage collector.
  PhantomReference - relate to cleanup tasks. They offer a notification
     immediately before the garbage collector performs the
     finalization process and frees an object.
     Consider it a way to do cleanup tasks within an object.
 
An object is strongly reachable if it can be reached by some thread without
  traversing any reference objects. A newly-created object is strongly reachable
  by the thread that created it.
An object is softly reachable if it is not strongly reachable but can be
  reached by traversing a soft reference.
An object is weakly reachable if it is neither strongly nor softly reachable
  but can be reached by traversing a weak reference. When the weak references
  to a weakly-reachable object are cleared, the object becomes eligible
  for finalization.
An object is phantom reachable if it is neither strongly, softly, nor weakly
  reachable, it has been finalized, and some phantom reference refers to it.
Finally, an object is unreachable, and therefore eligible for reclamation,
when it is not reachable in any of the above ways.
 *
 *
 * set classpath=.
 * javac GarbageTest.java
 * java -verbosegc -XX:+PrintGCDetails GarbageTest


big memory allocate =1
[GC [DefNew: 472K->64K(576K), 0.0042908 secs] 472K->295K(1984K), 0.0044052 secs]
[GC [DefNew: 489K->64K(576K), 0.0031271 secs] 720K->618K(1984K), 0.0032321 secs]
[GC [DefNew: 447K->64K(576K), 0.0035804 secs] 1001K->1001K(1984K), 0.0036793 secs]
[GC [DefNew: 576K->64K(576K), 0.0037334 secs][Tenured: 1449K->1130K(1536K), 0.0126976 secs] 1513K->1130K(2112K), 0.0172716 secs]
[GC [DefNew: 62K->62K(576K), 0.0008530 secs][Tenured: 1130K->1193K(1888K), 0.0120191 secs] 1193K->1193K(2464K), 0.0136869 secs]
[Full GC [Tenured: 1710K->158K(1888K), 0.0052575 secs] 1802K->158K(2464K), [Perm : 1028K->1028K(4096K)], 0.0061822 secs]
weak hash map empty

 */
public class GarbageTest {

   // Allocate lot of memory
   public static void testGarbage(boolean print) {
     List list = new ArrayList();
     for (int i = 0; i < 100000; i++) {
       if ((i % 1000) == 0)
          if (print) System.out.println("Created " + i);
       list.add(new Object());
     }
   }
 
   public static void references() {
     WeakHashMap weakHashMap = new WeakHashMap();
     weakHashMap.put(new String("Hello"), new String("World"));
     int i = 1;
     while (!weakHashMap.isEmpty()) {
       System.out.println("big memory allocate =" + i++);
       testGarbage(false);
       System.gc(); // not gauranteed to run
     }
     // weakHashMap should be empty after garabage collection
     if (weakHashMap.isEmpty())
        System.out.println("weak hash map empty");
   }
 
   public static void main(String[] args) {
     references();
   }
}