2010-08-27 14 views
10

Estoy intentando cargar clases dinámicamente en un componente. Estoy usando un selector de archivos para seleccionar el archivo .JAR que se cargará y luego un panel de opciones para obtener el nombre de la clase.Java dinámicamente Cargando una clase

He rastreado internet buscando la manera de convertir un archivo java a una URL con el fin de cargarlo en URLClassLoader y he llegado 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); 

recibo actualmente un 'no se puede encontrar el símbolo 'error al cargar la URL en el URLClassLoader

+1

¿Está 'traulled' una palabra? Lo único que google sugiere es 'trolled' :-) http://www.urbandictionary.com/define.php?term=trolled –

+0

@seanizer: "atravesado", desplazado, como parte de una búsqueda. – trashgod

+1

@trashgod que suena mucho mejor ... –

Respuesta

5

ClassPathHacker.java encontrado en this forum thread, es una opción para cargar las clases de forma dinámica.

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

me gusta la clase ClassPathHacker mencionado en the answer by Zellus, pero está lleno de llamadas en desuso y malas prácticas, por lo que aquí es una versión reescrita, que también almacena en caché el cargador de clase y el método 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

+ ¡para volver a factorizar! – trashgod

0

Reescribí esto en scala en caso de que alguien necesite ya que no es 100% trivial :)

/* 
* 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 
    } 
} 
Cuestiones relacionadas