2010-08-27 22 views
10

Sto tentando di caricare le classi dinamicamente in un componente. Sto usando un selettore di file per selezionare il file .JAR che verrà caricato e quindi un pannello delle opzioni per ottenere il nome della classe.Java Caricamento dinamico di una classe

ho spulciato internet alla ricerca di come convertire un file Java per un URL per caricarlo in URLClassLoader e sono venuto su con:

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); 

ora sto ottenendo un 'non riesce a trovare il simbolo 'errore nel caricamento dell'URL in URLClassLoader

+1

Viene "traullata" una parola? L'unica cosa che google suggerisce è "trolled" :-) http://www.urbandictionary.com/define.php?term=trolled –

+0

@seanizer: "trawled", attraverso, come parte di una ricerca. – trashgod

+1

@trashgod che suona molto meglio ... –

risposta

5

ClassPathHacker.java trovata in this forum thread, è la possibilità di caricare le classi in modo dinamico.

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

mi piace la classe ClassPathHacker di cui al the answer by Zellus, ma è pieno di chiamate deprecato e cattive pratiche, ecco una versione riscritta che memorizza anche il programma di caricamento classi e il metodo 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

+ per il re-factoring! – trashgod

0

ho riscritto questo in scala nel caso qualcuno ne abbia bisogno in quanto non è banale al 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 
    } 
} 
Problemi correlati