Est-il possible d'ajouter un fichier (pas nécessairement un fichier jar) à Java classpath au moment de l'exécution. Plus précisément, le fichier est déjà présent dans le classpath, ce que je veux, c'est si je peux ajouter un modifié copie de ce fichier dans le chemin de classe.
Merci,
Vous pouvez uniquement ajouter des dossiers ou des fichiers jar à un chargeur de classe. Donc, si vous avez un fichier de classe unique, vous devez d'abord le placer dans la structure de dossiers appropriée.
Ici est un hack plutôt laid qui s'ajoute à SystemClassLoader lors de l'exécution:
import Java.io.IOException;
import Java.io.File;
import Java.net.URLClassLoader;
import Java.net.URL;
import Java.lang.reflect.Method;
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
La réflexion est nécessaire pour accéder à la méthode protégée addURL
. Cela pourrait échouer s'il existe un SecurityManager.
Essayez celui-ci pour la taille.
private static void addSoftwareLibrary(File file) throws Exception {
Method method = URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{URL.class});
method.setAccessible(true);
method.invoke(ClassLoader.getSystemClassLoader(), new Object[]{file.toURI().toURL()});
}
Cela modifie le chargeur de classe système pour inclure le pot de bibliothèque donné. C'est assez moche, mais ça marche.
La façon dont je l'ai fait est d'utiliser mon propre chargeur de classe
URLClassLoader urlClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
DynamicURLClassLoader dynalLoader = new DynamicURLClassLoader(urlClassLoader);
Et créez la classe suivante:
public class DynamicURLClassLoader extends URLClassLoader {
public DynamicURLClassLoader(URLClassLoader classLoader) {
super(classLoader.getURLs());
}
@Override
public void addURL(URL url) {
super.addURL(url);
}
}
Fonctionne sans aucune réflexion
Vous pouvez essayer Java.net.URLClassloader avec l'url du dossier/jar où réside votre classe mise à jour et l'utiliser à la place du chargeur de classe par défaut lors de la création d'un nouveau thread.
Oui, je pense que c'est possible, mais vous devrez peut-être implémenter votre propre chargeur de classe. Je ne l'ai jamais fait, mais c'est la voie que j'examinerais probablement.
oui, vous pouvez. il devra être dans sa structure de package dans un répertoire séparé du reste de votre code compilé si vous souhaitez l'isoler. vous allez alors simplement mettre son répertoire de base à l'avant du chemin de classe sur la ligne de commande.