动态加载jar作为其他类的库

时间:2016-01-03 21:34:49

标签: java jar classpath

我正在为Web服务器应用程序开发一个插件系统,并且遇到了需要外部库(jar不是本机库)的插件的问题。由于我加载插件的方式(在应用程序启动后),我找不到动态加载这些jar库供插件使用的方法。

插件编译为jar,必须在jar中包含一个名为plugin.info的文件。此文件遵循以下格式:

main=x.y.z.PluginMainClass (the main class of the plugin to be loaded and instantiated by the application - as shown below)
load-lib=jsocket.jar
load-class=com.jsocket.Server
load-class=com.jsocket.Client

这是我加载插件的相关部分:

JarFile jarFile = new JarFile(file);
Enumeration<JarEntry> e = jarFile.entries();

URL[] urls = { new URL("jar:file:" + file.getPath() + "!/") };
URLClassLoader cl = URLClassLoader.newInstance(urls);

String pluginClass = "";
File loadLib = null;
URLClassLoader libLoader = null;

ArrayList<String> postLoad = new ArrayList<String>();
ArrayList<Class<?>> classes = new ArrayList<Class<?>>();
while (e.hasMoreElements()) {
    JarEntry je = (JarEntry) e.nextElement();
    if(je.isDirectory() || !je.getName().endsWith(".class")){
        if(je.getName().equals("plugin.info")){
            String dat = readStringFromJarEntry(je);
            for(String line : dat.split("\n")){
                String[] parts = line.split(Pattern.quote("="));
                if(parts.length < 2)continue;
                if(parts[0].equals("main"))
                    pluginClass = parts[1];
                else if(parts[0].equals("load-lib")){
                    File libFile = new File("./lib", parts[1]);
                    libLoader = URLClassLoader.newInstance(new URL[] { new URL("jar:file:" + libFile.getPath() + "!/") });
                }else if(parts[0].equals("load-class")){
                    libLoader.loadClass(parts[1]);//Class<?> cls = Class.forName(parts[1], true, libLoader);//THIS WORKS FINE WITH NO EXCEPTIONS
                }
            }
        }
        continue;
    }
    String className = je.getName().substring(0, je.getName().length() - 6);
    postLoad.add(className);
}
//Load all classes in plugin jar
for(String className : postLoad){
    log.d("Loading plugin class " + className);
    className = className.replace('/', '.');
    Class<?> c = cl.loadClass(className);
    classes.add(c);
}
jarFile.close();
for(Class<?> cls : classes){
    if(cls.getCanonicalName().equals(pluginClass)){
        Object plug = cls.newInstance();
        if(plug instanceof IPlugin){
            IPlugin iplug = (IPlugin)plug;
            plugins.add(iplug);//plugins is an arraylist of objects implementing IPlugin
        }
    }
}

(对不起,但是有必要使用冗长的代码)

以下是该插件主要类的片段:

@Override
public void init(){
    Server server = new Server(1221);//Reference to Server class in jsocker lib (first arg is port)
}

如您所见,该插件使用jsocket库中的类。我使用URLClassLoader#loadClass从jsocket lib加载了类,但在初始化插件时出现以下错误:

Exception in thread "main" java.lang.NoClassDefFoundError: com/jsocket/Server

如何修复此问题并将URLClassLoader#loadClass加载类转换为类路径?

0 个答案:

没有答案