Check out the new USENIX Web site.

Figure 1 - Tracing Method Execution

public class TraceMethod implements Constants {
  private static String          class_name;
  private static ConstantPoolGen cp;
  private static int             out;     // reference to System.out
  private static int             println; // reference to PrintStream.println

  private static Method traceMethod(Method m) {
    Code   code  = m.getCode();
    int    flags = m.getAccessFlags();
    String name  = m.getName();
	
    // Create instruction list to be inserted at method start.
    String mesg = "tracing " + m.getMethodName();
    InstructionList patch  = new InstructionList();
    patch.append(new GETSTATIC(out));
    patch.append(new PUSH(cp, mesg));
    patch.append(new INVOKEVIRTUAL(println));
	
    MethodGen           mg  = new MethodGen(m, class_name, cp);
    InstructionList     il  = mg.getInstructionList();
    InstructionHandle[] ihs = il.getInstructionHandles();

    // First let the super or other constructor be called
    if(name.equals("")) {
      for(int j=1; j < ihs.length; j++) {
	 if(ihs[j].getInstruction() instanceof INVOKESPECIAL) {
	   il.append(ihs[j], patch);  // Should check: method name == ""
	   break;
	 }
      }
    }
    else
      il.insert(ihs[0], patch);

    // update stack size
    if(code.getMaxStack() < 2)
	  mg.setMaxStack(2);
	
    return mg.getMethod();
  } 
     
  public static void main(String[] argv) { 
    JavaClass       java_class = new ClassParser(argv[i]).parse();
    ConstantPool    constants  = java_class.getConstantPool();
    cp = new ConstantPoolGen(constants);
    out     = cp.addFieldref("java.lang.System", "out",
				   "Ljava/io/PrintStream;");
    println = cp.addMethodref("java.io.PrintStream",
				    "println",
				    "(Ljava/lang/String;)V");

    Method[] methods = java_class.getMethods();
    for(int j=0; j < methods.length; j++)
      methods[j] = traceMethod(methods[j]);

    java_class.setConstantPool(cp.getFinalConstantPool());
    java_class.dump(class.getClassName()+".class");
  }
}

Return to paper