BCel修补方法在运行中无法正常工作

时间:2016-02-03 22:39:04

标签: java runtime bytecode bcel

我正在尝试使用BCEL将回调插入到Java方法中,但从不调用回调。这些程序就好像根本没有检测一样。

删除我所做的版本:

package com.github.worldsender;

import java.lang.reflect.InvocationTargetException;

import org.apache.bcel.*;
import org.apache.bcel.classfile.*;
import org.apache.bcel.generic.*;

public class CustomHook {
    public static void callback() {
        System.out.println("Success");
    }

    private static JavaClass getOriginal() {
        try {
            return Repository.lookupClass("com.github.worldsender.Foo");
        } catch (ClassNotFoundException e) {
            throw new RuntimeException("Foo not found.", e);
        }
    }

    private static ClassGen modClass(ClassGen classGen) {
        for (Method method : classGen.getMethods()) {
            if (!method.getName().equals("main"))
                continue;
            classGen.removeMethod(method);
            MethodGen methodGen = modConstructor(classGen, method);
            classGen.addMethod(methodGen.getMethod());
            methodGen.getInstructionList().dispose();
            return classGen;
        }
        throw new RuntimeException("Method not found, abort");
    }

    private static MethodGen modConstructor(ClassGen classGen, Method constructor) {
        InstructionFactory factory = new InstructionFactory(classGen);
        ConstantPoolGen constants = classGen.getConstantPool();
        MethodGen methodGen = new MethodGen(constructor, classGen.getClassName(), constants);

        InstructionList ilist = methodGen.getInstructionList();

        String invokedClass = "com.github.worldsender.CustomHook";
        String invokedMethod = "callback";
        Type returnType = Type.VOID;
        Type[] arguments = Type.NO_ARGS;
        short invokeType = Constants.INVOKESTATIC;
        InvokeInstruction invoke = factory.createInvoke(invokedClass, invokedMethod, returnType, arguments, invokeType);

        ilist.insert(invoke);
        methodGen.stripAttributes(true);
        methodGen.setMaxStack();
        methodGen.setMaxLocals();
        return methodGen;
    }

    public static void main(String[] args) throws Exception {
        JavaClass original = getOriginal();
        ClassGen modClass = new ClassGen(original);
        modClass = modClass(modClass);

        Repository.removeClass(original);
        Repository.addClass(modClass.getJavaClass());

        Class<?> minecraftMain = Class.forName("com.github.worldsender.Foo");

        java.lang.reflect.Method meth = minecraftMain.getMethod("main", String[].class);
        meth.invoke(null, (Object) args);
    }
}
//// Other class
package com.github.worldsender;

public class Foo {
    public static void main(String[] args) {
        System.out.println("Here");
    }
}

所有印刷品都是:

Here

我期待的是:

Success
Here

我做错了什么?

1 个答案:

答案 0 :(得分:1)

致电

Repository.addClass(modClass.getJavaClass())

您要将类添加到BCEL存储库,但不能添加到当前VM的类路径。致电时

Class.forName("com.github.worldsender.Foo")

但是,您正在指示VM从类路径加载未修改的类文件。因此,你无法观察到任何影响。查看BCEL的built-in class loader以加载生成的类。