Java动态加载类

时间:2010-08-27 01:38:35

标签: java swing dynamic classloader

我正在尝试将类动态加载到组件中。我正在使用文件选择器来选择将要加载的.JAR文件,然后使用选项窗格来获取类的名称。

我已经在互联网上搜索如何将java文件转换为URL以便在URLClassLoader中加载它我已经提出:

File myFile = filechooser.getSelectedFile();
String className = JOptionPane.showInputDialog(
    this, "Class Name:", "Class Name", JOptionPane.QUESTION_MESSAGE);

URL myUrl= null;
try {
    myUrl = myFile.toURL();
} catch (MalformedURLException e) {
}

URLClassLoader loader = new URLClassLoader(myUrl);
loader.loadClass(className);

我现在收到一个'无法找到符号'错误,无法将网址加载到URLClassLoader

5 个答案:

答案 0 :(得分:8)

我喜欢the answer by Zellus中提到的ClassPathHacker类,但它充满了不赞成的调用和不良做法,所以这里是一个重写版本,它还缓存了Classloader和addUrl方法:

import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.io.IOException;
import java.io.File;

public class ClassPathHacker{

    private static final Class<URLClassLoader> URLCLASSLOADER =
        URLClassLoader.class;
    private static final Class<?>[] PARAMS = new Class[] { URL.class };

    public static void addFile(final String s) throws IOException{
        addFile(new File(s));
    }

    public static void addFile(final File f) throws IOException{
        addURL(f.toURI().toURL());
    }

    public static void addURL(final URL u) throws IOException{

        final URLClassLoader urlClassLoader = getUrlClassLoader();

        try{
            final Method method = getAddUrlMethod();
            method.setAccessible(true);
            method.invoke(urlClassLoader, new Object[] { u });
        } catch(final Exception e){
            throw new IOException(
                "Error, could not add URL to system classloader");
        }

    }

    private static Method getAddUrlMethod()
        throws NoSuchMethodException{
        if(addUrlMethod == null){
            addUrlMethod =
                URLCLASSLOADER.getDeclaredMethod("addURL", PARAMS);
        }
        return addUrlMethod;
    }

    private static URLClassLoader urlClassLoader;
    private static Method addUrlMethod;

    private static URLClassLoader getUrlClassLoader(){
        if(urlClassLoader == null){
            final ClassLoader sysloader = 
                ClassLoader.getSystemClassLoader();
            if(sysloader instanceof URLClassLoader){
                urlClassLoader = (URLClassLoader) sysloader;
            } else{
                throw new IllegalStateException(
                    "Not an UrlClassLoader: "
                    + sysloader);
            }
        }
        return urlClassLoader;
    }

}

答案 1 :(得分:5)

this forum thread中找到的{p> ClassPathHacker.java是一个动态加载类的选项。

import java.lang.reflect.*;
import java.io.*;
import java.net.*;


public class ClassPathHacker {

private static final Class[] parameters = new Class[]{URL.class};

public static void addFile(String s) throws IOException {
    File f = new File(s);
    addFile(f);
}//end method

public static void addFile(File f) throws IOException {
    addURL(f.toURL());
}//end method


public static void addURL(URL u) throws IOException {

    URLClassLoader sysloader = (URLClassLoader)ClassLoader.getSystemClassLoader();
    Class sysclass = URLClassLoader.class;

    try {
        Method method = sysclass.getDeclaredMethod("addURL",parameters);
        method.setAccessible(true);
        method.invoke(sysloader,new Object[]{ u });
    } catch (Throwable t) {
        t.printStackTrace();
        throw new IOException("Error, could not add URL to system classloader");
    }//end try catch

}//end method

}//end class

答案 2 :(得分:2)

看看这个相关的问题:How should I load Jars dynamically at runtime?

答案 3 :(得分:1)

URLClassLoader takes an array of URLs的构造函数,而不是单个URL。

答案 4 :(得分:0)

我在scala中重写了这个,以防任何人需要,因为它不是100%琐碎:)

/*
 * Class which allows URLS to be "dynamically" added to system class loader
 */
object class_path_updater {
  val URLCLASSLOADER = classOf[URLClassLoader]

  var urlClassLoader = getUrlClassLoader
  var addUrlMethod = getAddUrlMethod

  /*
   * addFile - have to use reflection to retrieve and call class loader addURL method as it is protected
  */
  def addFile(s: String) = {
    val urlClassLoader = getUrlClassLoader
    try {
      val method = getAddUrlMethod
      method.setAccessible(true)
      val v = (new File(s)).toURI.toURL
      invoke(urlClassLoader, method, Array[AnyRef](v))
      def invoke(proxy: AnyRef, m: Method, args: Array[AnyRef]) = m.invoke(proxy, args: _*)
    }

  }

  private def getAddUrlMethod: Method = {
    if (addUrlMethod == null) addUrlMethod = URLCLASSLOADER.getDeclaredMethod("addURL", classOf[URL])
    addUrlMethod
  }

  private def getUrlClassLoader: URLClassLoader = {
    if (urlClassLoader == null) {
      val sysLoader = ClassLoader.getSystemClassLoader
      sysLoader match {
        case x: URLClassLoader => urlClassLoader = sysLoader.asInstanceOf[URLClassLoader]
        case _ => throw new IllegalStateException("Not a UrlClassLoader: " + sysLoader)
      }
    }
    urlClassLoader
  }
}