Will somone please take a quick look at the example below. I am trying to modify each
method in a class s.t. the first thing it does is allocate a new byte[] (for the
moment Im happy to just create it and let it go, ... I mean I dont need to bind it to
anything). I dont understand what more I am supposed to do to insert instructions in a
method. This code will result in an error like -
Exception in thread "main" java.lang.VerifyError: (class: tests/test1/Test, method:
main signature: ([Ljava/lang/String;)V) Unable to pop operand off an empty stack
Thanks,
Alan.
-----
public static void doit(final String sourcePath, final String className) throws
Exception
{ // Setup
org.apache.bcel.Repository.setRepository(org.apache.bcel.util.SyntheticRepository.getInstance(new
org.apache.bcel.util.ClassPath(sourcePath)));
final org.apache.bcel.classfile.JavaClass jc =
org.apache.bcel.Repository.lookupClass(className);
final org.apache.bcel.generic.ClassGen cg = new org.apache.bcel.generic.ClassGen(jc);
final org.apache.bcel.generic.ConstantPoolGen cpg = new
org.apache.bcel.generic.ConstantPoolGen(jc.getConstantPool());
cg.setConstantPool(cpg);
// For all the methods in the class, some new instructions
final org.apache.bcel.classfile.Method[] m = jc.getMethods();
for(int i = 0; i < m.length; i++)
{ org.apache.bcel.generic.MethodGen mg = new org.apache.bcel.generic.MethodGen(m[i],
className, cpg);
mg.setConstantPool(cpg);
org.apache.bcel.generic.InstructionList origIL = mg.getInstructionList();
org.apache.bcel.generic.InstructionHandle[] ih = origIL.getInstructionHandles();
org.apache.bcel.generic.InstructionFactory f = new
org.apache.bcel.generic.InstructionFactory(cg);
org.apache.bcel.generic.InstructionList newIL = new
org.apache.bcel.generic.InstructionList();
// Create a byte array
newIL.append(f.createNewArray(new
org.apache.bcel.generic.ArrayType(org.apache.bcel.generic.Type.BYTE, 1), (short)1));
if(m[index].getName().equals("<init>"))
{ // First let the super or other constructor be called
for(int j = 1; j < ih.length; j++)
{ if(ih[j].getInstruction() instanceof org.apache.bcel.generic.INVOKESPECIAL)
{ origIL.append(ih[j], newIL);
break;
}
}
}
else origIL.insert(ih[0], newIL);
mg.setMaxLocals();
mg.setMaxStack();
m[i] = mg.getMethod();
origIL.dispose(); // Reuse instruction handles
}
// Dump the modified class
jc.setMethods(m);
jc.setConstantPool(cpg.getFinalConstantPool());
jc.dump(System.out);
}