V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ccde8259
V2EX  ›  Java

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

  •  
  •   ccde8259 · 2021-06-29 19:42:18 +08:00 via iPhone · 1950 次点击
    这是一个创建于 1254 天前的主题,其中的信息可能已经有所发展或是发生改变。
    对于一个 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 直接操作内存方法?
    9 条回复    2021-06-30 09:21:23 +08:00
    2bab
        1
    2bab  
       2021-06-29 19:50:34 +08:00
    JVM TI 应该可以
    kiracyan
        2
    kiracyan  
       2021-06-29 19:51:19 +08:00
    匿名函数?
    yitingbai
        3
    yitingbai  
       2021-06-29 19:51:46 +08:00
    可以的, 你可以了解一下动态代理
    goinghugh
        4
    goinghugh  
       2021-06-29 20:07:25 +08:00
    jvm-sanbox? btrace? 运行期不重启 JVM 的 AOP
    ccde8259
        5
    ccde8259  
    OP
       2021-06-29 20:27:29 +08:00 via iPhone
    @yitingbai 动态代理可以,相应的限制 A 只能是 Interface,如果是 Class 的话就无能为力。
    类似 CGLIB 的字节码增强技术,并不能操作实例化后的对象。
    yitingbai
        6
    yitingbai  
       2021-06-29 20:36:00 +08:00
    @ccde8259 通用的替换方法那就是 Hook 了, 我在 Android 中经常使用, 有很多 Hook 框架, 但是 Java 这块我还真没研究过, 理论上来说应该也是有的
    zifangsky
        7
    zifangsky  
       2021-06-29 20:39:53 +08:00
    还有一种思路,自定义 ClassLoader 重新加载一个修改后的实例 B
    ccde8259
        8
    ccde8259  
    OP
       2021-06-29 20:48:05 +08:00 via iPhone
    @zifangsky 如果重新加载的话,实例 B 还会是实例 B 嘛……比如 C 对象持有 B 的引用的情况下,能否在不变更这个引用的前提下实现这种替换?
    siweipancc
        9
    siweipancc  
       2021-06-30 09:21:23 +08:00 via iPhone
    :D 你是要实现一个 jrebel
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5939 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 02:19 · PVG 10:19 · LAX 18:19 · JFK 21:19
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.