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