Reputation: 1309
I am new to BCEL for manipulating Java bytecode. I need to insert a new method into a particular line in a .class file using BCEL. The result should be a new .class file which contains the class with the newly inserted method.
I searched a lot online, but could not find a suitable code to follow. Can you please help me with this?
Thanks in advance!
Upvotes: 0
Views: 1568
Reputation: 630
I used GeekyArticles to figure out BCEL, maybe it helps you to? http://www.geekyarticles.com/search/label/BCEL
Anyway, the following code works for me (Java 1.7)
Test.java:
public class Test {}
AddMain.java:
import java.io.IOException;
import org.apache.bcel.classfile.*;
import org.apache.bcel.generic.*;
import org.apache.bcel.*;
public class AddMain {
static public void main(String args[]) {
String className = (args.length >= 1) ? args[0] : "";
JavaClass mod = null;
try {
mod = Repository.lookupClass(className);
}
catch (Exception e) {
System.err.println("Could not get class " + className);
}
ClassGen modClass = new ClassGen(mod);
ConstantPoolGen cp = modClass.getConstantPool();
InstructionList il = new InstructionList();
il.append(new GETSTATIC(cp.addFieldref("java.lang.System","out","Ljava/io/PrintStream;")));
il.append(new PUSH(cp, "Hello World!"));
il.append(new INVOKEVIRTUAL(cp.addMethodref("java.io.PrintStream","println","(Ljava/lang/String;)V")));
il.append(new RETURN());
MethodGen methodGen = new MethodGen(
Constants.ACC_PUBLIC|Constants.ACC_STATIC,
Type.VOID,
new Type[]{new ArrayType(Type.STRING, 1)},
new String[]{"args"},
"main",
className,
il,
cp);
methodGen.setMaxLocals();
methodGen.setMaxStack();
modClass.addMethod(methodGen.getMethod());
modClass.update();
try {
JavaClass newClass = modClass.getJavaClass();
String className2 = className.replace(".","/");
newClass.dump(className2 + ".class");
System.out.println("Class " + className + " modified");
}
catch (IOException e) {
e.printStackTrace();
}
}
}
Then use these commands in your terminal:
Generate AddMain.class:
javac -cp bcel-5.2.jar:. AddMain.java;
Generate Test.class:
javac Test.java;
Inject method named "main" in class Test.class:
java -cp bcel-5.2.jar:. AddMain Test;
Run Test.class to test:
java Test
And of course make sure you've got the bcel-5.2.jar file in that directory as well.
As far as I know you can't control the position of the injected method, but I'm not sure about that..
Upvotes: 1