【问题标题】:Java Dynamically Loading a classJava动态加载类
【发布时间】:2011-04-04 14:10:43
【问题描述】:

我正在尝试将类动态加载到组件中。我正在使用文件选择器来选择将要加载的 .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);

我现在在将 URL 加载到 URLClassLoader 时遇到“找不到符号”错误

【问题讨论】:

标签: java swing dynamic classloader


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      ClassPathHacker.javathis forum thread 中找到,是一个动态加载类的选项。

      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
      

      【讨论】:

        【解决方案4】:

        我喜欢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;
            }
        
        }
        

        【讨论】:

          【解决方案5】:

          我在 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
            }
          }
          

          【讨论】:

            猜你喜欢
            • 2012-10-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-11-05
            • 2011-02-19
            • 2016-03-12
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多