[英]Loading classes runtime in Java
我想提供一项服务,该服务运行24/7,可以加载新模块或已加载模块的较新版本,而无需重新启动它。
我可以从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”。 如果重新部署其中有错误的代码,并且需要完全重新启动才能恢复,则相同。
有时,您将需要升级您的操作系统,您的Java安装,您的appserver安装……以及其他需要(至少)需要重新启动服务的JVM的事情。
如果您的服务器出现硬件故障,则“ 24/7”服务将关闭。
我建议您使用(例如)一个HA代理来运行两个或三个服务实例。 当您要升级时,请删除一个实例,对其进行升级,然后“翻转” HA代理,以使升级后的实例成为“主要”实例。 然后重复直到所有实例都升级。 如果在升级最后一个实例之前出现问题,则可以选择回退到旧版本。
(在集群应用服务器平台上使用Web容器实现此功能是另一种同样有效的方法。)
显然,这要复杂得多,但是运行服务的多个实例是实现高可用性的正常方法。 如果您无力运行多个实例,那么做一些聪明的事情来避免服务器重新启动就不能完全满足“ 24/7”的要求。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.