在字节码中,使用BCEL将方法添加到类中的特定行

时间:2013-10-29 07:17:11

标签: java methods bytecode bcel

我是BCEL的新手,用于操作Java字节码。我需要使用BCEL将新方法插入到.class文件中的特定行。结果应该是一个新的.class文件,其中包含具有新插入方法的类。

我在网上搜索了很多,但找不到合适的代码。你能帮帮我吗?

提前致谢!

1 个答案:

答案 0 :(得分:1)

我用GeekyArticles来找出BCEL,也许它可以帮到你? http://www.geekyarticles.com/search/label/BCEL

无论如何,以下代码适用于我(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();
        }
    }
}

然后在终端中使用这些命令:

生成AddMain.class:

javac -cp bcel-5.2.jar:. AddMain.java; 

生成Test.class:

javac Test.java; 

注入方法名为" main"在Test.class类中:

java -cp bcel-5.2.jar:. AddMain Test; 

运行Test.class进行测试:

java Test

当然也要确保你在该目录中也有bcel-5.2.jar文件。

据我所知,你无法控制注射方法的位置,但我对此并不确定..