android - Android下如何交换方法体

标签 android dalvik dex java-assist

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

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

我已经检查了所有其他替代方案,例如 stackoverflow 中描述的那个, 它指向过时的 javassist-android执行。这出人意料地有效,但仅适用于新类(class)。

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

处理此问题的唯一文章是一篇名为 Android hacking: replacing system classes methods with your own 的文章,它缺少源代码并且指的是 Dalvik,而不是 ART(因此它不能在现代硬件上运行)。

那么,有什么办法可以做到吗?

...

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

最佳答案

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

".. we rely on runtime instrumentation that is supported in Android 8.0 (Oreo) and newer devices and emulators to redefine classes on the fly."


此外,在 episode 108 of ADB Podcast 中Esteban de la Canal 提到:

".. In Android Oreo (8.0), the platform implemented bytecode instrumentation on the fly, so we can actually change the dexed class of a running app.. by attaching, basically, an equivalent of JVMTI in Java, so we can attach an agent and say: can you swap this class with this one. "


从阅读 art/openjdkjvmti 开始来源,即 readme记录以下内容:

openjdkjvmti plugin
This is a partial implementation of the JVMTI v1.2 interface for the android runtime as a plugin. This allows the use of agents that can modify the running state of the program by modifying dex files in memory and performing other operations on the global runtime state.


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

关于android - Android下如何交换方法体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56513613/

相关文章:

Android:Activity.runOnUiThread 和 View.post 有什么区别?

android - 无法在android studio 0.2.3中创建新项目

java - DEX 和 Dalvik 是否支持 Java 二进制兼容性?

android - 对于 http 连接中的任何设备,dalvik 代理 header 是否唯一?

android java堆空间

android - 当我使用 Asynctask 时如何通知用户文件下载完成

database - 从 SQLite 数据库 Android 填充 Spinner

android - Dalvik VM 调用问题

android - play-services-base 和 support-v4 双方法计数

java - 安卓工作室 : 'C:\Program Files\Java\jdk1.8.0_51\bin\java.exe' ' finished with non-zero exit value 1