【发布时间】:2016-01-29 01:05:04
【问题描述】:
这是我正在努力解决的类加载器问题。我了解问题的根本原因(不同的类加载器),但我不确定修复它的最佳方法。
我有一些通用接口的项目;我们称之为api。我还有两个名为 runner 和 module 的项目,它们都使用 api 作为依赖项。
runner 的工作是动态加载一个module 工件(来自一个 jar;它是一个包含其依赖项的胖子),然后执行它。 runner 期望 module 提供来自 api 的某些具体实现。为了确保来自不同版本的 module.jar 的类不会相互冲突,我创建了一个新的类加载器,其 URL 为 module.jar,并将父类加载器设置为加载和处理 module.jar 的类的类加载器.这没有任何问题。
当我使用 runner 作为 web 应用程序(具体来说是一个 Spring Boot 应用程序)中的依赖项时出现了问题,并很快发现我无法从 module.jar 加载一些类,因为它们与已经存在的类冲突存在于当前类路径中(来自 webapp 中的其他依赖项)。
由于module.jar 真的只需要来自api 的类,我想我可以创建一个新的URLClassLoader(没有父级),它只有来自api.jar 的类,然后将其用作父类加载器当我加载模块时。这就是我开始遇到麻烦的地方:
CommonInterface commonInterface = null;
Class<CommonInterface> commonInterfaceClass = null;
ClassLoader myClassLoader = URLClassLoader.newInstance(moduleJarURL, apiClassesClassLoader);
//...
//...
//clazz is a concrete implementation from module.jar
if(myClassLoader.loadClass(CommonInterface.class.getName()).isAssignableFrom(clazz)) {
commonInterfaceClass = clazz;
}
commonInterface = commonInterfaceClass.newInstance(); //ClassCastException
我知道我最初的问题是由于类加载器在尝试加载它之前首先检查类是否已经加载,这意味着当它使用来自module.jar 的名称解决时,它正在链接不兼容的类版本。
有什么好的方法来处理这个问题?与其创建仅包含来自 api 的类的 URL 类加载器,不如创建我自己的实现,仅当请求的类是来自 api 的类时才委托给父级?
【问题讨论】:
标签: java classpath classloader