在运行时替换(覆盖)类实现 (Java)

发布于 2024-08-10 08:57:07 字数 522 浏览 3 评论 0原文

是否有任何方法可以替换(覆盖)已由系统类加载器加载的另一个实现(以字节数组形式提供)的 Java 类实现?

为了说明我的疑问,请遵循以下代码:

public class Main {
    public static void main(String ... args) {
        Foo foo = new Foo();
        foo.print();

        ClassLoader cl = ...

        Foo foo2 = (Foo) cl.newInstance();
        foo2.print();
    }
}

第一个 Foo 的 print() 方法打印“Implementation 1”,而第二个 Foo 则打印“Implementation 2”。 foo 的第二个实例由类加载器从字节数组中检索(可以存储在文件中,或从任何流中获取...)

PS:要求 Foo 是一个类,而不是一个接口,并且无法扩展,即定义类实现的实际字节(VM 内部)被覆盖。

Is there any way of substituting (overriding) a Java class implementation, which is already loaded by the System class loader by another implementation (available as an array of bytes)?

To illustrate my doubt, follows this code:

public class Main {
    public static void main(String ... args) {
        Foo foo = new Foo();
        foo.print();

        ClassLoader cl = ...

        Foo foo2 = (Foo) cl.newInstance();
        foo2.print();
    }
}

The print() method of the first Foo prints "Implementation 1", as the second one prints "Implementation 2". The second instance of foo is retrieved by the class loader from an array of bytes (which can be stored in a file, or got from any stream...)

PS: Is a requirement that Foo is a class, not an interface, and cannot be extended, i.e., the actual bytes (inside the VM) that defines the class implementation are overrided.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

合约呢 2024-08-17 08:57:07

是的,这没问题。您应该使用java.net.URLClassLoader。例如,您可以给它一个 url,它是您的覆盖 Foo.class 文件所在的目录。

编辑:
那么你想要的调用是cl.loadClass("Foo").newInstance()。您无法将结果强制转换为 Foo,但可以使用反射来调用其 print 方法。或者使 Foo 成为您不会重新实现的子类(或接口实现),该子类定义了 print 方法,并强制转换为该方法。

Yes, this is no problem. You should use a java.net.URLClassLoader. For example, you could give it a url which is a directory where your overriding Foo.class file lives.

Edit:
Then the call you want is cl.loadClass("Foo").newInstance(). You can't cast the result to a Foo, but you can use reflection to call its print method. Or make Foo a subclass (or interface implementation) of something you won't be reimplementing which defines a print method, and cast to that.

丑疤怪 2024-08-17 08:57:07

CGLib 就是这样做的。它用于 Spring 和 Spring 中。休眠就是为了这个目的。

CGLib does things like this. It is used in Spring & Hibernate for this purpose.

ㄟ。诗瑗 2024-08-17 08:57:07

您可以实现一个检测代理并使用 java.lang.instrument.Instrumentation#redefineClasses(...) 来替换已加载类的字节码。

You can implement an instrumentation agent and use java.lang.instrument.Instrumentation#redefineClasses(...) to replace the bytecode of already loaded classes.

青丝拂面 2024-08-17 08:57:07

我使用 JMX 取消部署和重新部署类。

I use JMX to undeploy and the redeploy classes.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文