Java 从拦截器bytebuddy调用超类方法

Java 从拦截器bytebuddy调用超类方法,java,bytecode-manipulation,byte-buddy,Java,Bytecode Manipulation,Byte Buddy,我们有一个模糊的类,需要用bytebuddy增强它。我们基本上需要重新定义一种方法。子类化似乎不起作用(代码未执行)。重定基可工作,但在我们截获的方法中,我们需要调用超类(现在称为“继承”中的超类)方法 class Parent { public void connect(){ ... }; } class WeNeedToHackThis extends Parent { public void connect(InetAddress addr){ //.

我们有一个模糊的类,需要用bytebuddy增强它。我们基本上需要重新定义一种方法。子类化似乎不起作用(代码未执行)。重定基可工作,但在我们截获的方法中,我们需要调用超类(现在称为“继承”中的超类)方法

class Parent {
  public void connect(){
  ...
  };
}

class WeNeedToHackThis extends Parent {
     public void connect(InetAddress addr){
       //... this is what we want to hack
     }
     public void connect(){
       this.connect(null);
       // this is getting called from interceptor :( which delegates to our hacked method
       // we need to call "real" superclass's (Parent) method instead
     }

}
...
Class<?> dynamic = new ByteBuddy()
            .with(TypeValidation.DISABLED)
            .rebase(commandBase, locator)
            .method(named("connect").and(takesArgument(0, InetAddress.class)))
            .intercept(MethodDelegation.to(Session3270ConnectMethod.class))
            .make()
            .load(Thread.currentThread().getContextClassLoader(), ClassLoadingStrategy.Default.INJECTION)
            .getLoaded();

//In our interceptor:
    public static void connect(InetAddress paramInetAddress,
            @Origin Method origin,
            @This Object self) throws SessionException {
        try {
            System.out.println("hi from hijacked");
            c.call();
            //HOW DO WE CALL SOMETHING LIKE super.connect()
            // we need to call Parent.connect(); 
            // but I am stuck at how to access superclass  code (new Parent().connect(). 
            // I cant access the Parent class method calls on this object
            // if I use @SuperCall or @This then I am getting already overriden version, I need to call the super (Parent's.class) version :(

        } catch (Exception e) {
            throw new RuntimeException(e);

        }
    }
类父类{
公共void connect(){
...
};
}
类WeNeedToHackThis扩展了父类{
公共无效连接(InetAddress addr){
//…这就是我们想要破解的
}
公共void connect(){
this.connect(null);
//这是从拦截器中调用的:(拦截器委托给我们被攻击的方法)
//我们需要调用“真实”超类的(父)方法
}
}
...
类dynamic=newbytebuddy()
.with(TypeValidation.DISABLED)
.rebase(命令库、定位器)
.method(命名为“connect”).and(takesArgument(0,InetAddress.class)))
.intercept(MethodDelegation.to(Session3270ConnectMethod.class))
.make()
.load(Thread.currentThread().getContextClassLoader(),ClassLoadingStrategy.Default.INJECTION)
.getLoaded();
//在我们的拦截器中:
公共静态无效连接(InetAddress paramInetAddress,
@起源方法起源,
@此对象(自身)引发SessionException{
试一试{
System.out.println(“hi from hijacked”);
c、 call();
//我们如何称呼像super.connect()这样的东西
//我们需要调用Parent.connect();
//但是我被困在如何访问超类代码(newparent().connect()。
//我无法访问此对象的父类方法调用
//如果我使用@SuperCall或@This,那么我已经得到覆盖版本,我需要调用super(Parent's.class)版本:(
}捕获(例外e){
抛出新的运行时异常(e);
}
}

如果我理解正确,您只希望在从类外部而不是从类内部调用方法调用时拦截该方法调用

这是一件很难实现的事情。Byte Buddy允许您将代码添加到任何类中,但即使是手动添加,也很难将代码输出

您最好的机会可能是添加一个线程本地存储来标记这种自调用,并在您只需委托给超级方法而不应用拦截器逻辑的情况下再次命中拦截器时检测它。

public static void connect(InetAddress paramInetAddress,
public static void connect(InetAddress paramInetAddress,
            @Super Object parentObj, @This Object myself, @SuperCall Callable<?> call) throws SessionException {
        try {
            System.out.println("hi from hijacked");
            parentObj.getClass().getMethods();
            Field IMPL_LOOKUP = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP");
            IMPL_LOOKUP.setAccessible(true);
            MethodHandles.Lookup lkp = (MethodHandles.Lookup) IMPL_LOOKUP.get(null);
            MethodHandle h1 = lkp.findSpecial(b.class, "connect", MethodType.methodType(void.class), Session3270.class);
            h1.invoke(myself);
        } catch (Throwable e) {
            throw new RuntimeException(e);

        }
    }
@超级对象parentObj、@This对象本身、@SuperCall Callable call)抛出SessionException{ 试一试{ System.out.println(“hi from hijacked”); parentObj.getClass().getMethods(); 字段IMPL_LOOKUP=MethodHandles.LOOKUP.class.getDeclaredField(“IMPL_LOOKUP”); IMPL_LOOKUP.setAccessible(true); MethodHandles.Lookup lkp=(MethodHandles.Lookup)IMPL_Lookup.get(null); MethodHandle h1=lkp.findSpecial(b.class,“connect”,MethodType.MethodType(void.class),Session3270.class); h1.调用(我自己); }捕获(可丢弃的e){ 抛出新的运行时异常(e); } }
好的,我看不太清楚:)-->“如何调用Parent.class类的'connect()'方法(这是类WeNeedToHackThis继承的父类-基本上我们需要在拦截器中执行:'super.connect()')事实上,我认为我仍然在正确的措辞上失败…无论如何,我能够解决它-请参阅下面我调用父类的答案(使用来自反射的方法委派).所以我加入了reflection&bytebuddy并实现了所需的功能。感谢您提供了一个很棒的lib-tho!啊,您是否尝试将超级对象设置为Parent类型?这样您就可以直接调用该方法了!我做到了,这就是我以java.lang.IllegalStateException:size=0 at net.bytebuddy.matcher.FilterableList$AbstractBase.getOnly结束的结果net.bytebuddy.implementation.auxiliary.TypeProxy$ForSuperMethodByConstructor.apply(TypeProxy.java:424)net.bytebuddy.implementation.bind.MethodDelegationBinder$ParameterBinding$Anonymous.apply(MethodDelegationBinder.java:222)…您能创建一个复制并通过GitHub作为bug提交吗?