如何替换Java中正在运行的应用程序中的类? [英] How to replace classes in a running application in java ?

查看:111
本文介绍了如何替换Java中正在运行的应用程序中的类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

说我有一个名为NameGenerator的类.我可以使用它根据给定的逻辑生成名称.然后,我编写一个TestNameGeneration类,该类使用一种向用户询问字母并根据其生成名称的方法.现在,我想更改NameGeneration类中的逻辑,并应用该特定更改而不停止应用程序.

Say I have a class named NameGenerator. I can use this to generate names according to a given logic. Then I write a TestNameGeneration class with a method that asks for a letter from the user and generate a name in accordance. Now I want to change the logic in NameGeneration class and apply that particular change without stopping the application.

我这样做是为了了解有关类加载器的更多信息,有人可以解释一下我必须学习的关键概念吗?要做类似的事情或查找任何参考文献?

I did this to learn more about class loaders and can someone please explain the key concepts that I have to learn to do something like that or site any references ?

推荐答案

这是一个有效的测试.每5秒钟Test.main()从文件系统重新加载test.Test1.class并调用Test1.hello()

Here is a working test. Every 5 secs Test.main() reloads test.Test1.class from the file system and calls Test1.hello()

package test;

public class Test1 {
    public void hello() {
        System.out.println("Hello !");
    }
}

public class Test {

    static class TestClassLoader extends ClassLoader {
        @Override
        public Class<?> loadClass(String name) throws ClassNotFoundException {
            if (name.equals("test.Test1")) {
                try {
                    InputStream is = Test.class.getClassLoader().getResourceAsStream("test/Test1.class");
                    byte[] buf = new byte[10000];
                    int len = is.read(buf);
                    return defineClass(name, buf, 0, len);
                } catch (IOException e) {
                    throw new ClassNotFoundException("", e);
                }
            }
            return getParent().loadClass(name);
        }
    }

    public static void main(String[] args) throws Exception {
        for (;;) {
            Class cls = new TestClassLoader().loadClass("test.Test1");
            Object obj = cls.newInstance();
            cls.getMethod("hello").invoke(obj);
            Thread.sleep(5000);
        }
    }
}

运行它.然后更改并重新编译Test1

Run it. Then change and recompile Test1

System.out.println("Hello !!!");

在测试运行时.您将看到Test1.hello输出更改

while Test is running. You will see Test1.hello output changed

...
Hello !
Hello !
Hello !!!
Hello !!!

例如,这就是Tomcat重新加载Web应用程序的方式.每个Web应用程序都有一个单独的ClassLoader,并在新的ClassLoader中加载新版本.就像任何Java对象以及旧类一样,旧的GC也被GCed.

This is how eg Tomcat reloads webapps. It has a separate ClassLoader for each webapp and loads a new version in a new ClassLoader. The old one is GCed just like any Java object as well as the old classes.

请注意,我们用TestClassLoader加载了Test1并通过反射调用了它的第一个方法.但是所有Test1依赖项都将通过Test1类加载器隐式加载,也就是说,所有Test1应用程序都将由JVM加载到TestClassLoader中.

Note that we loaded Test1 with TestClassLoader and invoked its first method with reflection. But all Test1 dependencies will be implicitly loaded with Test1 class loader, that is all the Test1 application will be loaded by JVM into TestClassLoader.

这篇关于如何替换Java中正在运行的应用程序中的类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆