当前位置: 首页 > 面试题库 >

如何替换Java中正在运行的应用程序中的类?

龚运乾
2023-03-14
问题内容

假设我有一个名为的课程NameGenerator。我可以使用它根据给定的逻辑生成名称。然后,我编写了一个TestNameGeneration类,该类使用一种向用户索要字母并根据其生成名称的方法。现在,我想更改NameGeneration类中的逻辑,并在不停止应用程序的情况下应用该特定更改。

我这样做是为了了解有关类加载器的更多信息,有人可以解释一些我必须学习的关键概念吗?


问题答案:

这是一个工作测试。每5秒钟Test.main()从文件系统重新加载test.Test1.class并调用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

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

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

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

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

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



 类似资料:
  • 问题内容: 我通常使用VisualVM对运行的Java应用程序进行概要分析,但它需要X才能在计算机上运行。 我知道我可以通过管理端口进行连接,但这将是一个脱机的概要分析,对我来说还不够。 因此,我正在寻找一种解决方案,可以通过命令行分析正在运行的Java应用程序方法的CPU使用率。对于我来说,在服务器上收集数据就足够了,然后可以在另一台计算机上分析收集的数据。 更新: 看来我需要更具体。我想从命令

  • 我有一个正在运行的Spark应用程序,它占据了所有核心,而我的其他应用程序将不会被分配任何资源。 我做了一些快速的研究,人们建议使用YARN kill或 /bin/spark-class来杀死命令。然而,我使用的是CDH版本, /bin/spark-class根本不存在,YARN kill应用程序也不起作用。 有人能和我一起吗?

  • 我使用JDK8制作了一个java应用程序,然后从JAR制作了一个可执行文件。 我已经使用launch4j从jar中创建了一个exe,并且没有可能选择Java11作为最新版本。 那么我怎样才能让这个exe在Java11上运行呢?

  • 我们有几个Java独立的应用程序(以Jar文件的形式)在多个服务器上运行。这些应用程序主要在系统之间读取和流式传输数据。我们主要在开发中使用Java8。我最近负责。我的主要功能是管理和维护这些应用程序。 目前,我通过访问这些服务器手动检查这些应用程序,检查应用程序是否正在运行,有时会运行一些数据库查询以查看应用程序是否开始提取数据。我的问题是,在许多情况下,其中一些应用程序由于数据问题或边缘情况而

  • 问题内容: 我正在研究非常庞大的基于Java Web的应用程序。由于在开发过程中没有完成正确的日志记录,因此我很难设置断点并调试应用程序,因为我不知道执行顺序。在执行一些操作之后,是否有任何机制可以获取正在运行的Java应用程序的完整调用堆栈。 我在网上搜索了很长时间,但无法找到具体的解决方案。如果有东西请给我建议。谢谢 问题答案: 方法1:从命令行使用Jstack实用程序(JDK发行版的一部分)

  • 问题内容: 我想知道如何在Java中运行PHP代码。使用ScriptEngine,我可以运行JavaScript: 为此,我导入了库。我相信要运行PHP,我必须导入一个类似的库,并将上面代码的第三行更改为extension 。不幸的是,我不知道这是哪个库。我已经用Google搜索并找到了答案,并遇到了PHP / Java Bridge库,但是我认为这并不是我要找的,因为它专注于通过PHP运行Jav