如何实现一次对象方法动态替换?

2021-06-29 19:42:18 +08:00
 ccde8259
对于一个 Class/Interface A 而言,不妨假设 A 有一个方法叫 call(),他的一个实例 B 在实例化以后这个 call()方法能不能被动态替换?
一个可行方法是你可以通过持有一个 Runnable 对象,在 call 方法里执行 run 方法。通过动态替换 Runnable 对象实现。以此类推 Consumer<T>,BiConsumer<T,U>对象适用于 call(T t)和 call(T t,U u)……但是更多参数呢?
实例化以后 B 对应的 Class 已经被加载到内存里了,有没有用 Unsafe 直接操作内存方法?
1946 次点击
所在节点    Java
9 条回复
2bab
2021-06-29 19:50:34 +08:00
JVM TI 应该可以
kiracyan
2021-06-29 19:51:19 +08:00
匿名函数?
yitingbai
2021-06-29 19:51:46 +08:00
可以的, 你可以了解一下动态代理
goinghugh
2021-06-29 20:07:25 +08:00
jvm-sanbox? btrace? 运行期不重启 JVM 的 AOP
ccde8259
2021-06-29 20:27:29 +08:00
@yitingbai 动态代理可以,相应的限制 A 只能是 Interface,如果是 Class 的话就无能为力。
类似 CGLIB 的字节码增强技术,并不能操作实例化后的对象。
yitingbai
2021-06-29 20:36:00 +08:00
@ccde8259 通用的替换方法那就是 Hook 了, 我在 Android 中经常使用, 有很多 Hook 框架, 但是 Java 这块我还真没研究过, 理论上来说应该也是有的
zifangsky
2021-06-29 20:39:53 +08:00
还有一种思路,自定义 ClassLoader 重新加载一个修改后的实例 B
ccde8259
2021-06-29 20:48:05 +08:00
@zifangsky 如果重新加载的话,实例 B 还会是实例 B 嘛……比如 C 对象持有 B 的引用的情况下,能否在不变更这个引用的前提下实现这种替换?
siweipancc
2021-06-30 09:21:23 +08:00
:D 你是要实现一个 jrebel

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/786540

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX