【问题标题】:Call superclass method from interceptor bytebuddy从拦截器 bytebuddy 调用超类方法
【发布时间】:2017-07-13 19:10:52
【问题描述】:

我们有一个混淆类,我们需要用 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);

        }
    }

【问题讨论】:

  • 好吧,我看不太清楚 :) --> "如何调用 Parent.class 类的 'connect()' 方法(这是 WeNeedToHackThis 类继承自的父类 - 基本上我们需要执行:拦截器内的“super.connect()”)

标签: java bytecode-manipulation byte-buddy


【解决方案1】:

如果我对你的理解正确,你只想拦截一个方法调用,如果它是从你的类外部调用而不是从内部调用。

这是一件很难实现的事情。 Byte Buddy 允许您向任何类添加代码,但即使是手动添加,也很难编写代码。

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

【讨论】:

  • 实际上我认为我在正确的措辞上仍然失败......无论如何我能够解决它 - 请参阅下面调用父类的答案(使用反射的方法委托)。所以我加入了reflection & bytebuddy 并实现了所需要的。感谢您提供了一个很棒的库!
  • 啊,您是否尝试过让 Super 对象为 Parent 类型?这样就可以直接调用方法了!
  • 我做到了,这就是我以 java.lang.IllegalStateException: size = 0 at net.bytebuddy.matcher.FilterableList$AbstractBase.getOnly(FilterableList.java:108) at net.bytebuddy 结束的。 implementation.auxiliary.TypeProxy$ForSuperMethodByConstructor.apply(TypeProxy.java:424) 在 net.bytebuddy.implementation.bind.MethodDelegationBinder$ParameterBinding$Anonymous.apply(MethodDelegationBinder.java:222) ...
  • 您能否创建一个复制品并通过 GitHub 将其作为错误提交?
【解决方案2】:
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);

        }
    }

【讨论】:

    猜你喜欢
    • 2020-08-17
    • 2021-05-17
    • 1970-01-01
    • 1970-01-01
    • 2020-02-20
    • 1970-01-01
    • 2012-08-18
    • 2015-08-14
    相关资源
    最近更新 更多