java - ByteBuddy - 无法从超类拦截静态方法
问题描述
我正在为 Android 开发命令行工具(想想我),试图利用 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。但是子类不包含任何方法。
用getMethods替换对getDeclaredMethods的调用我能够列出超类的所有公共方法。
通过将拦截的方法替换为非静态方法(例如“状态”),我可以使用 ByteBuddy 的getDeclaredMethods函数列出该方法:
keyStoreMethods 中声明的方法数:2
方法 = 公共 android.security.KeyStore$State AndroidKeyStoreMasker.state()
方法 = 公共 android.security.KeyStore$State AndroidKeyStoreMasker.state(int)
所以我的最终结论是 ByteBuddy(或我使用 ByteBuddy 的用例)在静态方法可见性方面存在一些问题。
任何帮助将不胜感激。
解决方案
创建subclass
Byte Buddy 时,只能拦截子类直接声明的方法或超类的虚方法。这就是 JVM 的工作方式,static
方法直接在接收器上分派。
Byte Buddy 也能够重新定义和重新转换现有的类,但这需要 Android 上不可用的 Java 代理。因此,恐怕您需要找到一个非静态挂钩点来完成您正在尝试的事情。或者,看看MemberSubstitution
您可以从代码中重定向此类调用的位置。这也需要重新转换,但由于它发生在您的代码中,您可以使用 Byte Buddy 的构建插件。
推荐阅读
- c# - 使用 VB.Net 从 XML 中删除基于值的属性值
- javascript - discord.js bot await 仅在异步函数中有效
- excel - 从一维数组中选择随机项目不重复
- ios - Xcode 在运行测试时每秒都无法导入模块
- python - 如何减少python中的嵌套块字典
- apache-kafka - Kafka Connect Hive 集成不会创建 Hive 表
- c# - asp.net c#文件上传工作正常,但在服务器中部署时出错
- android - 如何“A RenderFlex 在底部溢出 61 个像素。” 在Android虚拟键盘的顶部
- powerbi - 应该对 power-bi 中的数据模型进行哪些更改以适应以下内容?
- android - Android 和 iOS 应用程序在不使用第三方的情况下通知用户的最佳选择是什么?