简体   繁体   中英

Substitute (override) class implementation at Runtime (Java)

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, ie, the actual bytes (inside the VM) that defines the class implementation are overrided.

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.

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

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM