以下 Java 代码在自主计算领域有何用处?

How is the following Java code useful, in the realm of autonomic computing?

在我正在学习的一本书中,他们展示了这个 Java 代码:

Class c = ClassLoader.getSystemClassLoader().loadClass(name);
Class type = this.getClass().getClassLoader().loadClass(name);
Object obj = type.newInstance();

此代码用于动态加载Javaclass。这本书继续:

unloading modules raises an issue. A class loader cannot unload a class. Unloading a class requires unloading the class loader itself. This is why programmers .. tend to define several class loaders.

使用这样的代码有什么好处?自主计算的思想通常是 - "autonomic system administration." 这与 Java 程序如何受 JVM 控制有何关系?

来源:自主计算原理设计第 166 页(Lalanda 着)

好处是您可以在 运行 时决定实际加载和使用什么 class。对于只有一个 class 实现的简单 Java 程序,没有任何好处。

像 Osgi(Eclipse 的基础)这样的复杂环境为每个模块使用单独的 classloader。这带来了灵活性和在 运行 时间内更换模块的可能性。

另一个 "classical" 用例是在 运行 时间内加载数据库驱动程序。您可能想要连接到 MySQL 数据库或 Oracle,并且两者都使用不同的 JDBCDriver 实现。

加法:

可以在 here.

上找到 Alex Blewitt 的一篇非常好的文章,其中讨论了 eclipse/osgi class 加载概念

根据我自己的编码经验,我将 eclipse 插件用于企业级 Web 监控项目。监控基本上与不断抓取网络上的一些资源有关。每个此类资源都由监视器插件的实现监视。并非所有资源都由我们控制,因此当它们发生变化时,我们必须调整处理该资源的插件。当我们针对新插件模块卸载旧插件模块时,整个监控应用程序可以继续运行。全部在运行时间内,几乎没有宕机(只针对需要更换的模块) 当然,我对每个插件的classloader的使用是通过使用Eclipse Rich Client Platform(RCP)隐含的).您只需要指定哪个插件依赖于哪个插件,然后实际 class 加载由 RCP 平台完成。

像 Tomcat 这样的网络服务器使用相同的方法,尽管我对 Tomcat 没有太多经验。

直接实现动态 class 加载系统可能是一个很好的练习,但对于现实世界的应用程序,我肯定会研究生产级实现,例如 Eclipse RCP or Apache Karaf

如果您想更进一步并需要 运行 集群中的插件,您可能需要查看 Gyrex

我不能在这里分享我的代码,但这里有一些很好的起点和代码示例:

假设以下示例。你开发一个程序。用户可以为它编写一些插件(或自主程序上下文中的代理)。您的程序将加载配置变量中定义的所有插件(或自定义代理 classes),例如:

plugins: foo.bar.myplug,another.plugin

在这种情况下,您需要动态加载 属性 中列举的 classes。这些class在你开发主程序的时候是未知的,正常class加载是不能用的

此外,如果出于任何原因您想卸载这些 classes(例如,在重新阅读配置后),您将需要一个自定义 class 加载器。

附录

例如,我们可以想象一个带有 "world" 的程序,其中一些 "agents" 进行交互。除了主程序中包含的几个代理之外,用户还可以创建自己的代理。

主程序将负责代理之间的交互(世界规则):向代理发送事件;更新考虑到代理人行为的世界状况;保存、加载世界; ……

每个代理都是一个 Java class,必须包含一个由主程序调用的方法 "public Action handleEvent( Event )"。默认情况下,存在一些预定义的 class,例如 "Person.class"、"SearchRobot.class",每个都有自己的 "handleEvent" 实现。它们都扩展了抽象 class "Agent".

该程序允许用户创建自己的代理。用户必须创建一个包含方法 "handleEvent" 的新 class(扩展代理)。以用户 class "WalkerAgent.class" 为例,他有一条探索世界的短路径。

主程序还将有一个名为 "plugins" 的 属性。此 属性 必须包含用户代理列表:

plugins: foo.bar.WalkerAgent 

当主程序启动时,它应该加载"plugins" 属性中列举的所有classes。类似于(伪代码):

 read property "plugins" and split it by ","
 for each split in previous:
    call loadClass

为了创建 class 代理的新实例 "WalkerAgent" 你不能在主程序中写一个 "new WalkerAgent()" 因为 class 不存在编写主程序时。相反,您必须调用 Class 的 "newInstance()" 即 "loadClass" returns。

现在,代理 "WalkerAgent" 可以像预定义代理 "Person" 和 "RobotSearch" 一样使用了。

(PS:显然,在自主计算中,举例来说,世界是一个网络描述,代理会执行 "monitor IP"、"route optimizer"、...等操作。此示例使用了更简单的概念以便于理解)。