Classloading可以保存,添加,恢复,一遍又一遍吗?

时间:2013-10-08 13:57:30

标签: java groovy classpath

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

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

稍后,当下一次'更新'到来时,我希望能够恢复原始类路径,然后重复使用更新的条目调用'addURL'的过程。然后这个过程在几天/几周后重复。我是否克隆原始的classLoader?我正在尝试做什么?好像任何人都不能说,我对类加载器做的并不多,而且我很茫然。我从一个java jar文件运行groovy,所以直接使用Java或Groovy解决方案都可以工作!

修改

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

2 个答案:

答案 0 :(得分:0)

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

不需要将jar添加到原始类加载器或尝试更改它,而是需要一个子类加载器,其中包含要更改的jar(并且父级不应该使用它们)。要添加,请创建一个新的此类子加载器。恢复基本上是通过JVM的垃圾收集完成的,然后你可以一遍又一遍地完成。但是你应该在这里使用版本化的jar,因为覆盖现有的jar可能是不可能的(在windows上,因为jar可能会被打开)或者导致非常奇怪的文物。

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

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

答案 1 :(得分: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代码会随着时间的推移重复执行上面的这四行。如果有以前的dynamicLoader,则会立即重置并修改类路径,并使用更新的jar列表。