0

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

私は何を間違っていますか?

4

1 に答える 1

1

通話時

Repository.addClass(modClass.getJavaClass())

クラスを BCEL リポジトリに追加していますが、現在の VM のクラス パスには追加していません。通話時

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

ただし、変更されていないクラス ファイルをクラス パスからロードするように VM に指示しています。したがって、効果を観察することはできません。生成されたクラスをロードするための BCEL の組み込みクラス ローダーを見てください。

于 2016-02-04T13:25:05.397 に答える