2010-08-27 5 views
10

Я пытаюсь динамически загружать классы в компонент. Я использую выбор файла, чтобы выбрать файл .JAR, который будет загружен, а затем панель параметров, чтобы получить имя класса.Java Dynamically Загрузка класса

Я тралил интернет в поисках, как преобразовать 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

+1

Is 'traulled' word? Единственное, что предлагает Google, - это «троллинг» :-) http://www.urbandictionary.com/define.php?term=trolled –

+0

@seanizer: «trawled» -sifted through, как часть поиска. – trashgod

+1

@trashgod, который звучит намного лучше ... –

ответ

5

ClassPathHacker.java найдено в this 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 
8

Мне нравится класс ClassPathHacker упоминается в the answer by Zellus, но она полна устаревших звонков и плохих практик, так вот переписана версия, которая также кэширует 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; 
    } 

} 
+0

+ для повторного факторинга! – trashgod

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 
    } 
} 
Смежные вопросы