0

我有一个长期存在的程序,需要在运行时动态更新类路径。

没问题 - 类加载器是一个 URLClassLoader,我调用了“addURL”方法。这一切都适用于一次“更新”迭代。

稍后,当下一个“更新”到来时,我希望能够恢复原始类路径,然后使用更新的条目重复调用“addURL”的过程。然后这个过程在几天/几周后重复。我要克隆原始的类加载器吗?我正在尝试做的事情可能吗?好像任何人都无法分辨,我对类加载器做的不多,而且很茫然。我正在从 java jar 文件运行 groovy,因此直接使用 Java 或 Groovy 解决方案都可以!

编辑

根据下面的问题。为了继续正确运行,我需要“刷新”我对类路径所做的原始更改,否则可能会在更新后无意中拾取这些更改。另外,我担心类路径上同时有多个版本的相同 jar。示例:在第一次加载时,我添加了 myJar1、myJar2 和 log4j(<- 即不是我的一个 jar 文件),在下一次更新时,我可能需要添加 myJar1 和 myJar2 的更新版本,以及 myJar3 和 log4j . 这更有意义吗?

4

2 回答 2

0

如果其他人需要这个作为参考,使用@blackdrag 答案,我创建了这个Java类:

public class DynamicClassLoader extends URLClassLoader {

    public DynamicClassLoader(ClassLoader parent, URL... urls) {
        super(urls, parent);
    }

    public void addURLs(Iterable<URL> urls) {
        for (URL url : urls) {
            addURL(url);
        }
    }

    public void resetThreadContextLoader() {
        Thread currentThread = Thread.currentThread();
        currentThread.setContextClassLoader(getParent());
    }
}

我的使用模型来自 groovy。因此,为了使用它,我所做的只是:

def myClassLoader = Thread.currentThread().contextClassLoader
dynamicLoader?.resetThreadContextLoader()
dynamicLoader = new DynamicClassLoader(myClassLoader)
dynamicLoader.addURLs(myListOfJarURLs)

完美运行。一切都非常简单——我的 groovy 代码将随着时间的推移重复执行上述四行代码。如果有以前的动态加载器,那么类路径会被重置并立即使用更新的 jar 列表进行修改。

于 2013-10-15T13:50:56.570 回答
0

如何克隆类加载器?通常你不会。您改为创建一个子加载器。

您不需要将 jars 添加到原始类加载器或尝试更改它,而是需要一个包含要更改的 jars 的子类加载器(并且父级不应拥有它们)。要添加您,请创建一个新的此类 childloader。恢复基本上是由 JVM 的垃圾收集完成的,然后您可以一遍又一遍地进行。但是你应该在这里使用版本化的 jar,因为覆盖现有的 jar 可能是不可能的(在 Windows 上,因为 jar 可能保持打开状态)或导致非常奇怪的工件。

如果您的程序本身依赖于您想要更改的 jar 中的类,那么您需要将程序更改为不依赖它 - 或者最好放弃这个想法。

如果由于某种原因你仍然想克隆并且你的加载器真的是一个普通的 URLClassLoader 只从 URL 加载(例如这在 GroovyClassLoader 上不起作用)那么你可以使用反射来访问字段 ucp 和那个对象字段 urls,它是一个堆栈,应该包含您要查找的信息。但请注意,在 99% 的情况下,这是错误的方式

于 2013-10-09T13:24:10.043 回答