3

在纯 Java 中,使用 intrumentation 和 java 代理,有一种方法可以在运行时替换方法体。

不幸java.lang.instrument.Instrumentation的是,在 Android 下不可用。

我已经检查了所有其他替代方案,例如stackoverflow中描述的替代方案,它指向过时的javassist-android实现。这令人惊讶地有效,但仅适用于新课程。

还有一篇名为Hot swapping code in Android的文章描述了如何在运行时再次加载类,而不是如何替换现有的类方法。

唯一涉及此问题的文章是一篇名为Android hacking: Replace system classes methods with your own的文章,该文章遗漏了源代码并引用了 Dalvik,而不是 ART(因此它不适用于现代硬件)。

那么,有没有办法做到这一点?

...

底线:我想要这样做的原因是在我的应用程序中跟踪特定的方法调用,就像调用此方法时(并在它之前执行一些操作)以及仅当此方法退出时(并对它执行一些操作)。这些方法是在运行时定义的,因此无法在编译时提前知道它们。

4

2 回答 2

5

Android Studio 3.5 中的一项新功能是Apply Changes,它基本上执行与您希望实现的逻辑类似的逻辑:

“.. 我们依靠 Android 8.0 (Oreo) 和更新的设备和模拟器支持的运行时检测来动态重新定义类。”


此外,在亚行播客Esteban de la Canal的第 108 集中提到:

“.. 在 Android Oreo (8.0) 中,平台即时实现了字节码检测,因此我们实际上可以更改正在运行的应用程序的 dexed 类.. 基本上,通过附加 Java 中的 JVMTI等价物,我们可以附加一个经纪人说:你能不能把这个班换成这个班。”


从阅读art/openjdkjvmti源代码开始,即自述文件包含以下内容:

openjdkjvmti 插件
这是 JVMTI v1.2 接口的部分实现,用于 android 运行时作为插件。这允许使用可以通过修改内存中的 dex 文件以及对全局运行时状态执行其他操作来修改程序运行状态的代理。


一旦 Android Studio 3.5 的源代码发布,看看他们如何在Apply Changes实现中使用这些新 API。

于 2019-06-09T16:28:47.983 回答
1

尽管 jlinstrument API 从未添加到 android 中,但用于实现它们的底层 JVMTI api 已添加到 Android O 中。例如,这里有一个测试 JVMTI 代理,它将重新定义列出的类并在每个方法的开头添加一个 nop:https://android.googlesource.com/platform/art/+/refs/heads/master/tools/jvmti-agents/simple-force-redefine/

于 2019-09-23T18:07:38.583 回答