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 の順序をソートすると、問題が解決します。

しかし、それは別の問題を提起します

詳細はこちら

AB のような同じパッケージ構造の 2 つの jar ファイルがありますが、そのうちの 1 つだけが MyClass2 を持っています。問題の原因は、MyClass2 を持つ jar の前に MyClass2 を持たない jar が読み込まれたことでした。URLClassLoader は、パッケージ AB を持つが MyClass2 クラスを持たない最初の jar を認識し、NoClassDefFoundError をスローします。MyClass2 を持つ jar を並べ替えた後、最初にロードされ、ClassLoader がクラスを見つけるためにベールされます。

この動作についてはよくわかりません。私自身、それと混同しています。

于 2013-05-09T02:01:45.190 に答える