【发布时间】:2019-11-21 17:12:17
【问题描述】:
免责声明:我知道有很多关于类加载的问题,但我还没有找到解决方案......
我的类路径中有一个依赖于动态加载的类的类。现在我可以在 java 8 上加载该类,但在以后的版本中这是一个问题。
在我的类路径中,我有 c:/git/udevelop91/JAVA/usoft.jar 包含 com.usoft.birt.ReportEngine 类。为了让这个类工作,我需要c:/ReportEngine/lib 中的罐子。这些 jar 之一包含 PlatformConfig。当我单独加载平台配置时,它工作正常并且类得到解决。当我尝试加载 ReportEngine 类但是失败了。因为它依赖于 LibraryClassLoader 中的 platformconfig。我也将 usoft.jar 添加到 LibraryClassLoader 以查看它是否有效,但似乎它继续使用 AppClassLoader 而不是我的 LibraryClassLoader 导致NoClassDefFoundError。如何在不从类路径中删除 usoft.jar 并且不将所有 birt jar 添加到类路径的情况下解决这个问题?所以reportEngineInst 的行失败了
public void loadIt(){
File f = new File("C:/ReportEngine/lib");
File[] files = f.isDirectory() ? f.listFiles() : new File[] {f};
URL[] urlss = new URL[files.length];
int i = 0;
for(File ff : files){
urlss[i++] = ff.toURI().toURL();
}
LibraryClassLoader urlloader = new LibraryClassLoader(urlss, ClassLoader.getSystemClassLoader());
urlloader.addJar("c:/git/udev/JAVA/USoft.jar");
Class<?> platformLoader = Class.forName("org.eclipse.birt.core.framework.PlatformConfig",true,urlloader);
Class<?> report = urlloader.loadClass("com.usoft.birt.ReportEngine");
// ---------- The line below fails with a NoClassDefFoundError ----------
Object reportEngineInst = report.getDeclaredConstructor(String.class, String.class).newInstance("c:/ReportEngine", "c:/ReportEngine");
}
public class LibraryClassLoader extends URLClassLoader{
public LibraryClassLoader( URL[] urls, ClassLoader parent) {
super(urls, parent);
}
public void addJar(String path) throws MalformedURLException {
super.addURL(Paths.get(path).toUri().toURL());
}
}
【问题讨论】:
-
您能否描述一下为什么您不愿意将所有必要的 JAR 放入类路径中?这似乎是最明显的解决方案,但您似乎正在放弃它。
-
@Simon 因为它不是基本产品附带的东西。这是我想稍后加载的扩展。我更有可能提取 com.usoft.birt.* 代码并稍后将其添加到 urlclassloader 而不是类路径中
-
如果您将“null”作为父类加载器传递给LibraryClassLoader,它是否有效? (如果是这样,可能不是最好的解决方案,但可能有助于理解原因)
-
@Simon 是的,它确实适用于
null。这是因为类加载器会首先向其父级询问类的方式吗? -
是的,通过将 getSystemClassLoader 作为父级,您让 LibraryClassLoader 首先要求父级加载类。这将适用于 PlatformConfig,因此该类将来自不同的 Classloader。通过设置 parent=null,您将强制 LibraryClassLoader 从头开始加载所有必需的类。这可能会导致许多类冗余加载,您必须弄清楚这是否可以接受
标签: java classloader