2

我正在使用 URLClassLoader 加载类。

尽管我传递的文件的名称已成功加载,但对于它所引用的类,则会为这些类抛出 NoClassDefFoundError。这两个类都是不同 jar 文件的一部分。

更奇怪的是,同一段代码在 Windows 上运行良好,但在 Linux 上却抛出错误。

这是我正在使用的代码:

package com.pb.spectrum.lim.upgrade.common;

 import java.io.File;
 import java.io.FilenameFilter;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLClassLoader;
 import java.util.ArrayList;
 import java.util.List;

 public class ClassInvoker {

public static void main(String[] args) throws MalformedURLException, ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    if(args.length < 2){
        throw new IllegalArgumentException("First argument should be Class name. Second argument should be jar's directory. Rest of the arguments passed to main method of invoked class.");
    }

    File jarsDir = new File(args[1]);
    if(!jarsDir.isDirectory()){
        throw new IllegalArgumentException("Second argument should point to jar's directory.");
    }

    URLClassLoader urlClassLoader = null;

    List<URL> urls = new ArrayList<URL>();
    File[] files = jarsDir.listFiles(new FilenameFilter() {
        @Override
        public boolean accept(File dir, String name) {
            return name.toLowerCase().endsWith(".jar");
        }
    });

    for(File jarFile : files){
        urls.add(jarFile.toURI().toURL());
    }
    urlClassLoader = new URLClassLoader(urls.toArray(new URL[urls.size()]));

    Thread.currentThread().setContextClassLoader(urlClassLoader);

    Object[] params = new String[args.length-2];

    // First 2 arguments are not required for class to be invoked.
    System.arraycopy(args, 2, params, 0, params.length);

    for(Object string : params){
        System.out.println("Param ---->" + (String)string);
    }

    Class clazz = urlClassLoader.loadClass(args[0]);
    Method method = clazz.getMethod("main", new Class[]{String[].class});
    method.invoke(null, new Object[] {params});
}
    }

现在,如果我将要加载的类传递为 ABMyClass1,它会成功加载,但无法加载单独的 jar 文件中的 ABMyClass2。

4

1 回答 1

0

那么我的问题已经解决了,但我不确定这个问题的原因。

总结一下:

正在加载的 jar 序列导致了这个问题。在我的特殊情况下,在将列表提供给 URLClassLoader 之前对 jar 的顺序进行排序可以解决问题。

但它提出了另一个问题

这是详细信息

我有两个具有相同包结构的 jar 文件,例如 AB,但其中只有一个具有 MyClass2。现在问题的原因是在具有 MyClass2 的 jar 之前加载了没有 MyClass2 的 jar,并且不知何故(我不知道如何或为什么)URLClassLoader 看到第一个 jar 具有包 AB 但没有 MyClass2 类并抛出 NoClassDefFoundError。排序后,首先加载具有 MyClass2 的 jar,ClassLoader 可以定位该类。

我不确定这种行为。我自己对此感到困惑。

于 2013-05-09T02:01:45.190 回答