59 votes

Comment voulez-vous changer le chemin de classe à l'intérieur de Java?

Comment voulez-vous changer le chemin de classe d'un processus Java à partir de l'intérieur du processus Java?


Avant de me demander "Pourquoi voudriez-vous faire cela?" Je vais vous expliquer en peu de temps.

Lorsque vous avez un Clojure REPL cours d'exécution, il est commun à besoin de plus de pots dans votre CLASSPATH pour charger un Clojure fichier source, et j'aimerais le faire sans avoir à redémarrer Clojure lui-même (qui n'est pas vraiment une option lors de l'utilisation sur vase sur Emacs).

C'est la raison, mais je ne veux pas que cette question étiqueté comme quelques-bizarre-langue quelques-bizarre-éditeur et d'être ignoré par la majorité des développeurs Java qui peut avoir la réponse.

78voto

VonC Points 414372

Quelques remarques générales:

vous ne pouvez pas (de façon portable qui est garanti de fonctionner, voir ci-dessous) changer le système classpath. Au lieu de cela, vous devez définir un nouveau chargeur de classe.

Chargeurs de classes travaillent dans une manière hiérarchique... de sorte que toute la classe qui fait une référence statique de la classe X qui doit être chargé dans le même chargeur de classe X, ou dans un chargeur de classe de l'enfant. Vous ne pouvez PAS utiliser ClassLoader personnalisé afin de rendre le code chargé par le système de chargeur de classe lien correctement, si il n'aurait pas fait avant. Si vous avez besoin pour organiser votre principale de l'application du code à exécuter dans le ClassLoader personnalisé en plus le code supplémentaire que vous recherchez.
(Cela dit, fissuré de toutes les citations dans les commentaires de cet exemple de l'extension de l' URLClassLoader)

Et vous pouvez envisager de ne pas écrire votre propre chargeur de classe, mais il suffit d'utiliser URLClassLoader à la place. Créer un URLClassLoader avec une url qui ne sont pas dans les chargeurs de classes parent url.

URL[] url={new URL("file://foo")};
URLClassLoader loader = new URLClassLoader(url);

Une solution plus complète serait:

ClassLoader currentThreadClassLoader
 = Thread.currentThread().getContextClassLoader();

// Add the conf dir to the classpath
// Chain the current thread classloader
URLClassLoader urlClassLoader
 = new URLClassLoader(new URL[]{new File("mtFile").toURL()},
                      currentThreadClassLoader);

// Replace the thread classloader - assumes
// you have permissions to do so
Thread.currentThread().setContextClassLoader(urlClassLoader);

Si vous assumez la Jvm système de chargeur de classe est un URLClassLoader (qui peut ne pas être vrai pour toutes les machines virtuelles), vous pouvez utiliser la réflexion ainsi de réellement modifier le système classpath... (mais c'est un hack;)):

public void addURL(URL url) throws Exception {
  URLClassLoader classLoader
         = (URLClassLoader) ClassLoader.getSystemClassLoader();
  Class clazz= URLClassLoader.class;

  // Use reflection
  Method method= clazz.getDeclaredMethod("addURL", new Class[] { URL.class });
  method.setAccessible(true);
  method.invoke(classLoader, new Object[] { url });
}

addURL(new File("conf").toURL());

// This should work now!
Thread.currentThread().getContextClassLoader().getResourceAsStream("context.xml");

3voto

Jon Skeet Points 692016

Je ne crois pas que vous pouvez - la bonne chose à faire (je crois) est de créer un nouveau chargeur de classe avec le nouveau chemin d'accès. Alternativement, vous pouvez écrire votre propre classloader qui vous permet de modifier le classpath (pour le loader) de manière dynamique.

Sinon, avez-vous essayé d'utiliser java.ext.dirs pour spécifier un répertoire à partir duquel de trouver les fichiers jar? Je soupçonne qu'il ne capte pas les fichiers jar ajoutés après le démarrage, mais il peut être la peine d'essayer.

2voto

myfreeweb Points 919

Il n'y a pas besoin d'écrire votre propre chargeur de classe! Il y a clojure.lang.DynamicClassLoader.

http://blog.japila.pl/2011/01/dynamically-redefining-classpath-in-clojure-repl/

1voto

Jack Leow Points 11081

Vous pouvez l'examiner à l'aide de java.net.URLClassLoader. Il vous permet de charger par programme des classes qui n'étaient pas à l'origine dans votre classpath, mais je ne sais pas si c'est exactement ce dont vous avez besoin.

1voto

PintSizedCat Points 4221

Il est possible que le voir sur les deux liens ci-dessous, la méthode VonC donne semble être la meilleure mais de vérifier certains de ces postes et google pour "Java Dynamique Classpath" ou "Java Dynamique de Chargement de Classe", et découvrez des infos à partir de là.

J'ai poster plus en profondeur, mais VonC a à peu près fait le travail.

De chargement Dynamique de classe et les fichiers Jar.

Vérifiez également ce soleil post sur le forum.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X