【问题标题】:NoClassDefFoundError - Dynamic loading Classpath Class dependency loaded in URLClassLoaderNoClassDefFoundError - 动态加载 URLClassLoader 中加载的 Classpath 类依赖项
【发布时间】: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


【解决方案1】:

Simon 的 cmets 帮助我意识到我无法使用 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[] {});
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-07
    相关资源
    最近更新 更多