java - NoClassDefFoundError - 动态加载类路径类依赖项在 URLClassLoader 中加载

标签 java classloader

免责声明:我知道有很多关于类加载的问题,但我还没有找到解决方案......

我的类路径中有一个类,它依赖于动态加载的类。现在我可以在 java 8 上加载该类,但在更高版本上这是一个问题。

在我的类路径上,我有 c:/git/udevelop91/JAVA/usoft.jar 其中包含 com.usoft.birt.ReportEngine 类。为了让这个类工作,我需要 c:/ReportEngine/lib 中的 jars。这些 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());
    }   
}

eclipse variables at runtime

最佳答案

Simon 的评论帮助我意识到我无法使用 SystemClassLoader。为了继续在类路径上使用具有相同类的当前解决方案,并稍后添加特定类,我现在拥有:

public void loadIt() throws Exception{
    /*Instantiate list for own classloader*/
    ArrayList<URL> urlss = new ArrayList<>();

    /*First fix the default classpath dependencies. usoft.jar is normally on the classpath*/
    for(String pathEntry : System.getProperty("java.class.path").split(System.getProperty("path.separator"))) {
        File fPathEntry = new File(pathEntry);
        File[] fPathEntries = fPathEntry.isDirectory() ? fPathEntry.listFiles() : new File[] {fPathEntry};
        for(File f : fPathEntries)
            urlss.add(f.toURI().toURL());
    }

    /*Now add the specific stuff*/
    File f = new File("C:/ReportEngine/lib");
    File[] files = f.isDirectory() ? f.listFiles() : new File[] {f};
    for(File ff : files)
        urlss.add(ff.toURI().toURL());

    /* 
       Make the classloader with the PlatformClassLoader as a parent 
       instead of the SystemClassLoader. I tried without a parent
       classloader, but then you cant find the platform classes 
       like java.sql.* 
    */
    URLClassLoader urlloader = new URLClassLoader(urlss.toArray(new URL[urlss.size()]), ClassLoader.getPlatformClassLoader());  

    /*And now it magically works*/
    Class<?> platformLoader = Class.forName("org.eclipse.birt.core.framework.PlatformConfig",true,urlloader);
    Class<?> report = Class.forName("com.usoft.birt.ReportEngine",true,urlloader);
    Object a = report.getDeclaredConstructor(String.class, String.class).newInstance("c:/reportEngine", "c:/reportEngine")  ;
    Method m = report.getMethod("generateDOC", String.class, String.class, Object[].class);
    m.invoke(a,"","",new Object[] {});
}

关于java - NoClassDefFoundError - 动态加载类路径类依赖项在 URLClassLoader 中加载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58912324/

相关文章:

java - 在 Mac 上使用 Resin 3.1.x 配置 JRebel 5

java - Class.forName() 和 ClassNotFoundException

java - 如何在第三方类中为 java.util.Random 提供特定种子?

Java ClassLoader - 将动态加载的 jar 添加到系统类加载器

java - 将 Oracle 身份验证迁移到表

java - 如何在处理数据时禁用按钮并更改按钮名称

java - 如何使用java在同一方法中更新具有不同字符串值的变量?

java - 将 Map 转换为 XML 而不使用 JAXB

java - SlowAES加密和java解密

Java,获取实现特定接口(interface)的 URLClassLoader 可用的所有类