1

我正在尝试动态加载 .jar 文件中包含的类。我知道整个类名,并且我确定该类实现了接口 AlgorithmClass。我的代码如下所示:

addURLToSystemClassLoader(dir.toURI().toURL());
Class cl = Class.forName(algorithm.getClassName());
AlgorithmClass algorithmClass = (AlgorithmClass)cl.newInstance();

其中dir是 .jar 文件的 File 对象,addURLToSystemClassLoader(URL) 如下所示:

private void addURLToSystemClassLoader(URL url) throws IntrospectionException {
        URLClassLoader systemClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
        Class<URLClassLoader> classLoaderClass = URLClassLoader.class; 
        try {
            Method method = classLoaderClass.getDeclaredMethod("addURL", new Class[]{URL.class});
            method.setAccessible(true);
            method.invoke(systemClassLoader, new Object[]{url});
        } catch (Throwable t) {
            t.printStackTrace();
            throw new IntrospectionException("Error when adding url to system ClassLoader ");
        }
    }

我检查并正在将 URL 添加到类加载器中。

当我尝试获取 Class 对象时,出现错误:

严重:javax.servlet.ServletException:java.lang.ClassNotFoundException:id3.Algorithm

(id3.Algorithm 是我要加载的类的全名)

我尝试创建一个新的 ClassLoader,如下所示:

ClassLoader cload = new URLClassLoader(new URL[]{dir.toURI().toURL()}, ClassLoader.getSystemClassLoader());
Class cl = Class.forName(algorithm.getClassName(), false, cload);
AlgorithmClass algorithmClass = (AlgorithmClass)cl.newInstance();

但后来我得到了错误:

java.lang.NoClassDefFoundError: lib/algorithm/AlgorithmClass

我尝试使用系统类加载器具有的所有 URL 创建一个新的 URLClassLoader,但效果是一样的。

“最糟糕”的部分是这两种方法在我用来测试这部分代码的 jUnit 测试中都运行良好。

我使用 Glassfish 3.1.1 作为我的应用服务器。

4

2 回答 2

1

dir 不应包含“lib”。试试这个:

 ClassLoader cload = new URLClassLoader(new URL[]{dir.toURI().toURL()}, Thread.currentThread().getContextClassLoader());
 Class cl = Class.forName(algorithm.getClassName(), true, cload);
 AlgorithmClass algorithmClass = (AlgorithmClass)cl.newInstance();
于 2012-05-09T08:20:02.240 回答
0

你有类加载问题。你应该知道,你addURLToSystemClassLoader()实际上是见鬼......

将你的 jar 放到类路径中。使用Class.forName()成语。如果失败,则使用接收 ClassLoader 作为参数的版本

   public static Class<?> forName(String name, boolean initialize,
                               ClassLoader loader)

和路径Thread.currentThread().getContextClassLoader()作为 ClassLoader 参数。

另请参阅下面我的另一个答案。

于 2012-05-09T08:15:45.473 回答