Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/391.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中加载运行时类_Java_Dynamic Class Loaders - Fatal编程技术网

在Java中加载运行时类

在Java中加载运行时类,java,dynamic-class-loaders,Java,Dynamic Class Loaders,我想做一个服务,它全天候运行,可以加载新模块或已加载模块的更新版本,而无需重新启动 我可以用如下方式从jar文件加载类: @FunctionalInterface public interface IWorker { void doStuff(); } IWorker worker; try { URL[] urls = { new URL("jar:file:" + "C:\\Users\\...\\out\\artifacts\\workers_jar\\something

我想做一个服务,它全天候运行,可以加载新模块或已加载模块的更新版本,而无需重新启动

我可以用如下方式从jar文件加载类:

@FunctionalInterface
public interface IWorker {
    void doStuff();
}
IWorker worker;
try {
    URL[] urls = { new URL("jar:file:" +  "C:\\Users\\...\\out\\artifacts\\workers_jar\\somethingworker.jar"  +"!/") };
    ClassLoader cl = new URLClassLoader(urls);
    Class cls = cl.loadClass("hu.test.worker.SomethingWorker");
    worker = (IWorker) cls.newInstance();
    worker.doStuff();
} catch (MalformedURLException e) {
    e.printStackTrace();
} catch (ClassNotFoundException e) {
    e.printStackTrace();
} catch (InstantiationException e) {
    e.printStackTrace();
} catch (IllegalAccessException e) {
    e.printStackTrace();
}

软件已经使用数据库表对从模块加载的类进行了一些配置,因此如果我在那里存储完整的类名(可能还有JAR的路径),我可以使用它。我的问题是,我能不能用更好的方法?这有点难以维护,很容易损坏,而且我不知道是否可以用它加载已加载的类。

以下是一些可能损坏的东西:

  • Windows可能会阻止您更新JAR文件,因为Java会在类加载器处于活动状态时锁定JAR文件

  • 内存泄漏。每次创建新的类加载器时,都有可能泄漏上一个类加载器。它所需要的只是前一个加载程序加载的一个类的一个实例仍然是可访问的,并且最终加载程序及其加载的所有类也是可访问的

  • 可能出现“奇怪”行为,因为您有两个或多个同名的类。您不会从根本上破坏运行时类型系统(JVM比这更聪明),但您会发现类型强制转换等意外失败

  • 如果重新部署时出现问题,您需要完全重新启动,那么您就不再是“24/7”。如果重新部署有bug的代码,并且需要完全重新启动才能恢复,则情况也是如此

  • 有时,您需要升级操作系统、Java安装、appserver安装。。。以及其他需要(至少)重启服务JVM的事情

  • 如果服务器出现硬件故障,则“24/7”服务将停止

  • 我建议您运行两个或三个服务实例,前面有一个HA代理(例如)。当您想要升级时,您需要取下一个实例,升级它,然后“翻转”HA代理,使升级的实例成为“主”。然后重复,直到所有实例都升级。如果在升级最后一个实例之前出现问题,您可以选择返回到旧版本

    (在集群appserver平台上使用web容器实现这一点是另一种同样有效的方法。)


    显然,这比这要复杂一些,但运行多个服务实例是实现高可用性的正常方法。如果您负担不起运行多个实例,那么做一些巧妙的事情来避免服务器重新启动并不能完全满足“24/7”的要求。

    以下是一些可能出现问题的地方:

  • Windows可能会阻止您更新JAR文件,因为Java会在类加载器处于活动状态时锁定JAR文件

  • 内存泄漏。每次创建新的类加载器时,都有可能泄漏上一个类加载器。它所需要的只是前一个加载程序加载的一个类的一个实例仍然是可访问的,并且最终加载程序及其加载的所有类也是可访问的

  • 可能出现“奇怪”行为,因为您有两个或多个同名的类。您不会从根本上破坏运行时类型系统(JVM比这更聪明),但您会发现类型强制转换等意外失败

  • 如果重新部署时出现问题,您需要完全重新启动,那么您就不再是“24/7”。如果重新部署有bug的代码,并且需要完全重新启动才能恢复,则情况也是如此

  • 有时,您需要升级操作系统、Java安装、appserver安装。。。以及其他需要(至少)重启服务JVM的事情

  • 如果服务器出现硬件故障,则“24/7”服务将停止

  • 我建议您运行两个或三个服务实例,前面有一个HA代理(例如)。当您想要升级时,您需要取下一个实例,升级它,然后“翻转”HA代理,使升级的实例成为“主”。然后重复,直到所有实例都升级。如果在升级最后一个实例之前出现问题,您可以选择返回到旧版本

    (在集群appserver平台上使用web容器实现这一点是另一种同样有效的方法。)


    显然,这比这要复杂一些,但运行多个服务实例是实现高可用性的正常方法。如果您负担不起运行多个实例,那么做一些巧妙的事情来避免服务器重新启动并不能完全满足“24/7”的要求。

    一个经典的方法是在基础架构级别而不是代码级别处理这一问题。具有两个应用程序实例的负载平衡器。若要部署新版本的软件,请从负载平衡器中删除一个实例,更新并重新启动此实例,然后将其返回LB,删除并更新第二个实例,并将其返回LB。我是否需要一些重型框架来实现此目的?如果应用程序无状态且不使用会话,比设置上面的要容易得多。否则,必须在会话同步方面付出一些努力,但这仍然是可行的。为此,您需要一个容器,如Tomcat或WebLogic,并设置一个集群环境(->负载平衡器)。好的一点是它不需要复杂的编码一个经典的方法是在基础架构级别而不是代码级别处理这个问题。具有两个应用程序实例的负载平衡器。要部署新版本的软件,请从负载平衡器中删除一个实例,更新并重新启动此实例,然后将其返回到LB,删除并更新第二个实例,并将其返回到LB。我是否需要一些重型框架来实现此目的?如果应用程序是无状态的且不使用会话,则很容易使用