【问题标题】:ByteBuddy - unable to intercept static method from superclassByteBuddy - 无法从超类拦截静态方法
【发布时间】:2020-08-17 17:37:46
【问题描述】:

我正在开发适用于 Android 的命令行工具(想想 am),试图利用 ByteBuddy 的强大功能来存根 android.security.KeyStore 中定义的静态方法 getApplicationContext

但是,当子类化 android.security.KeyStore 时,ByteBuddy getDeclaredMethods 似乎看不到该方法,因此无法拦截它。

当使用反射 API 中的 getMethods 时,我能够列出该方法。

            Class AndroidKeyStore = Class.forName("android.security.KeyStore");
            Method[] keyStoreMethods =  new ByteBuddy()
                      .with(TypeValidation.DISABLED)
                      .subclass(AndroidKeyStore, ConstructorStrategy.Default.IMITATE_SUPER_CLASS)
                      .name("KeyStoreMasker")
                      .method(ElementMatchers.named("getApplicationContext"))
                      .intercept(SuperMethodCall.INSTANCE)
                      .make()
                      .load(getClass().getClassLoader(),
                            new AndroidClassLoadingStrategy
                            .Injecting(new File("/data/app/cmdutil")))
                      .getLoaded()
                      .getDeclaredMethods();
            for(i = 0; i < keyStoreMethods .length; i++) {
                System.out.println("method = " + keyStoreMethods[i].toString());
            }

在运行上述代码时,我希望在子类中有一个方法 - getApplicationContext。但是子类不包含任何方法。

getDeclaredMethods 调用替换为 getMethods 我可以列出超类的所有公共方法。

通过将拦截的方法替换为非静态方法(例如“状态”),我可以使用 ByteBuddy 的 getDeclaredMethods 函数列出该方法:

keyStoreMethods 中声明的方法数:2

method = public android.security.KeyStore$State AndroidKeyStoreMasker.state()

method = public android.security.KeyStore$State AndroidKeyStoreMasker.state(int)

所以我的最终结论是 ByteBuddy(或我使用 ByteBuddy 的用例)在静态方法可见性方面存在一些问题。

参考android.security.KeyStore.java: https://android.googlesource.com/platform/frameworks/base/+/master/keystore/java/android/security/KeyStore.java

任何帮助将不胜感激。

【问题讨论】:

    标签: java android byte-buddy


    【解决方案1】:

    创建subclass时,Byte Buddy只能拦截子类直接声明的方法或超类的虚方法。这就是 JVM 的工作方式,static 方法直接在接收器上分派。

    Byte Buddy 也能够重新定义和重新转换现有的类,但这需要一个 Java 代理,而 Android 上没有。因此,恐怕您需要找到一个非静态挂钩点来完成您正在尝试的事情。或者,查看MemberSubstitution,您可以在其中从您的代码重定向此类调用。这也需要重新转换,但由于它发生在您的代码中,您可以使用 Byte Buddy 的构建插件。

    【讨论】:

    • 感谢您的回复。由于我没有任何非静态挂钩点选项,因此我选择了您的第二个产品 - 使用 bytebuddy 的 Maven 构建插件。但是 - 由于来自被调用类的方法没有在我的代码中定义并且被反射引用,我不知道如何利用你的建议。 android.security.KeyStore 类在构建时不可用。那么 - 我错过了什么?
    • 您需要替换代码中调用相关方法的调用。这可以在构建时完成。
    猜你喜欢
    • 1970-01-01
    • 2013-11-13
    • 2021-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多