Herong's Tutorial Notes on JVM
Dr. Herong Yang, Version 3.00, 2007

Garbage Collection

Part:   1  2  3  4  5  6  7  8  9 

This chapter explains:

  • GCTest Program
  • GCTest Program Output - Constant Memory Requirement
  • GCTest Program Output - Periodical Memory Requirement
  • Comparison - Releasing Old vs. New Objects
  • Comparison - JDK 1.4.0 vs. JDK 1.3.1
  • Comparison - Client vs. Server
  • Comparison - JDK 1.6.0 vs. 1.4.0

GCTest Program

We all know that objects that are not referenced will be removed from memory by the garbage collector. But we don't know how this process works exactly. I wrote the following program to try to figure this out.

/**
 * GCTest.java
 * Testing garbage collection behavior. 
 * Suggested JVM options: -Xms2m -Xmx8m
 * Copyright (c) 2003 by Dr. Herong Yang
 */
import java.util.*;
class GCTest {
   static MyList objList = null;
   static int wait = 500; // milliseconds
   static int initSteps = 16; // 2 MB 
   static int testSteps = 1;
   static int objSize = 128; // 1/8 MB
   public static void main(String[] arg) {
      if (arg.length>0) initSteps = Integer.parseInt(arg[0]);
      if (arg.length>1) testSteps = Integer.parseInt(arg[1]);
      objList = new MyList();
      Monitor m = new Monitor();
      m.setDaemon(true);
      m.start();
      myTest();	
   }
   public static void myTest() {
      for (int m=0; m<initSteps; m++) {
         mySleep(wait);
         objList.add(new MyObject());
      }
      for (int n=0; n<10*8*8/testSteps; n++) {
         for (int m=0; m<testSteps; m++) {
            mySleep(wait);
            objList.add(new MyObject());
         }
         for (int m=0; m<testSteps; m++) {
            mySleep(wait);
            objList.removeTail();
            // objList.removeHead();
         }
      }
   }
   static void mySleep(int t) {
      try {
         Thread.sleep(t);
      } catch (InterruptedException e) {
         System.out.println("Interreupted...");
      }
   }
   static class MyObject {
      private static long count = 0;
      private long[] obj = null;
      public MyObject next = null;
      public MyObject prev = null;
      public MyObject() {
         count++;
         obj = new long[objSize*128];
      }
      protected final void finalize() {
         count--;
      }
      static long getCount() {
         return count;
      }
   }
   static class MyList {
      static long count = 0;
      MyObject head = null;
      MyObject tail = null;
      static long getCount() {
         return count;
      }
      void add(MyObject o) {
      	 // add the new object to the head;
         if (head==null) {
            head = o;
            tail = o; 
         } else {
            o.prev = head;
            head.next = o;
            head = o;
         }
         count++;
      }
      void removeTail() {
      	 if (tail!=null) {
      	    if (tail.next==null) {
      	       tail = null;
      	       head = null;
      	    } else {
      	       tail = tail.next; 
      	       tail.prev = null;
      	    }
      	    count--;
      	 }
      }
      void removeHead() {
      	 if (head!=null) {
      	    if (head.prev==null) {
      	       tail = null;
      	       head = null;
      	    } else {
      	       head = head.prev;
      	       head.next = null;
      	    }
      	    count--;
      	 }
      }
   }
   static class Monitor extends Thread {
      public void run() {
         Runtime rt = Runtime.getRuntime();
         System.out.println(
            "Time   Total   Free   Free   Total   Act.   Dead   Over");
         System.out.println(
            "sec.    Mem.   Mem.   Per.    Obj.   Obj.   Obj.   Head");
         long dt0 = System.currentTimeMillis()/1000;
         while (true) {
            long tm = rt.totalMemory()/1024;
            long fm = rt.freeMemory()/1024;
            long ratio = (100*fm)/tm;
            long dt = System.currentTimeMillis()/1000 - dt0;
            long to = MyObject.getCount()*objSize;
            long ao = MyList.getCount()*objSize;
            System.out.println(dt 
               + "   " + tm + "   " + fm + "   " + ratio +"%"
               + "   " + to + "   " + ao + "   " + (to-ao) 
               + "   " + (tm-fm-to));
            mySleep(wait);
      	 }
      }
   }
}

(Continued on next part...)

Part:   1  2  3  4  5  6  7  8  9 

Dr. Herong Yang, updated in 2007
Herong's Tutorial Notes on JVM - Garbage Collection