在Java

时间:2016-03-27 00:44:57

标签: 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\\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的路径),我可以使用它。我的问题是,我能以更好的方式做到这一点吗?这有点难以维护并且可以轻松破解,我也不知道如果我可以用它加载已加载的类。

1 个答案:

答案 0 :(得分:3)

以下是一些可能会破坏的事情:

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

  2. 内存泄漏。每次创建新的类加载器时,都可能泄漏前一个。它所需要的只是前一个加载器加载的一个类的一个实例仍然可以访问,并且你最终得到了加载器,它加载的所有类也是可以访问的。

  3. "奇怪的"行为,因为您有两个或多个具有相同名称的类。你根本不打破运行时类型系统(JVM比那更聪明),但你发现类型转换等意外失败。

  4. 如果您的重新部署出现问题,并且您需要重新启动,则不再是" 24/7"。如果您重新部署包含错误的代码并且需要完全重新启动以进行恢复,则相同。

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

  6. 如果您的服务器出现硬件故障,那么您的" 24/7"服务下降。

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

    (在群集应用服务器平台上使用Web容器实现此功能是另一种同样有效的方法。)

    显然,它比这更复杂,但运行多个服务实例是实现高可用性的常规方法。如果你无法承担运行多个实例的费用,那么做一些聪明的事情以避免服务器重启并不能完全解决这个问题。" 24/7"要求。