import java.io.*;
import java.net.*;

public class st {
  public static void main(String[] args) {
    gc_monitor_thread gcm = new gc_monitor_thread();
    gcm.start();
    trace_thread  tt = new trace_thread();
    tt.start();
    for (int i = 0; i < 4; i++) {
      string_thread st = new string_thread();
      st.start();
    }
  }
}

class string_thread extends Thread {
  boolean alive = false;
  String tstr = "abc";
  public void run() {
    alive = true; 
    long lcnt = 0;
    int  mcnt = 0;
    while (alive) {
      String s = getName() + Long.toHexString(lcnt);
      if (s.equals(tstr)) mcnt++;
      s.intern();
      lcnt++; 
      if (lcnt % 100000 == 0) {
        try { Thread.sleep(10); } catch (InterruptedException ie) {}
      }
    }
  }
}

class trace_thread extends Thread {
  boolean alive = false;
  public void run() {
    alive = true;
    while (alive) {
      long t0 = System.currentTimeMillis();
      for (int i = 0; i < 100; i++) {
        do_stack_trace_op();
      }
      long t1 = System.currentTimeMillis();
      
      System.out.println("time for trace: " + (t1 - t0));
      try { Thread.sleep(1000); } catch (InterruptedException ie) {}
    }
  }
  void do_stack_trace_op() {
    Throwable t = get_throwable();
    PrintWriter pw = null;
    // try {
      pw = new PrintWriter(new StringWriter());
      t.printStackTrace(pw);
    // } catch (IOException ioe) {
    //   System.out.println(ioe);
    //   System.exit(2);
    // }
  }
  Throwable get_throwable() {
    return new Throwable("dummy");
  }
}

class gc_monitor_thread extends Thread {
  boolean alive = false;
  public void run() {
    alive = true;
    int try_limit = 100;
    int try_count = 0;
    while (alive) {
      int pn = 12345;
      ServerSocket ss = null;
      while (ss == null) {
        try {
          ss = new ServerSocket(pn);
        } catch (IOException ioe) {
          pn++;
          try_count++;
          if (try_count > try_limit) {
            System.out.println("too many failures while creating server socket.");
            System.out.println("exitting...");
            System.exit(2);
          }
        }
      }      

      if (ss == null) {
        System.out.println("unexpected situation.  server socket null");
        System.exit(3);
      }

      System.out.println("GC monitor thread started on port " +
        ss.getLocalPort() + ". Connect to this port to run GC.");

      while (alive) {
        Socket s = null;
        try {
          s = ss.accept(); 
        } catch (IOException ioe) {
          System.out.println("GC monitor thread got an exception in accept.");
          ioe.printStackTrace();
          System.exit(4);
        }

        if (s == null) {
          System.out.println("accept returned a null Socket.");
          System.exit(5); 
        }
        System.out.print("Performing System.gc()...");
        System.out.flush();
        System.gc();
        System.out.println("done.");
        try {
          s.close(); 
        } catch (IOException ioe) {
          System.out.println("error while closing socket.");
          ioe.printStackTrace();
        }
      }
    }
  }
}
