2016-02-03 76 views
0

我試圖用BCEL插入一個Java方法的回調函數,但回調函數從未被調用過。這些程序運行起來好像根本沒有插裝。BCel修補了一個不能正常工作的方法

剝離下來的我就是這樣做的版本:

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

當調用

Repository.addClass(modClass.getJavaClass()) 

要添加類的BCEL庫而不是當前的VM的類路徑。當致電

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

但是,您正在指示VM從類路徑加載未修改的類文件。因此,您無法觀察到任何影響。查看BCEL的built-in class loader加載生成的類。