web-dev-qa-db-de.com

Hinzufügen von Dateien zu Java classpath zur Laufzeit

Ist es möglich, eine Datei (nicht unbedingt eine JAR-Datei) zu Java= classpath zur Laufzeit hinzuzufügen. Insbesondere ist die Datei bereits im classpath vorhanden. Ich möchte nur, ob ich eine geänderte Datei hinzufügen kann Kopie dieser Datei in den Klassenpfad.

Vielen Dank,

62
rdsr

Sie können einem Klassenladeprogramm nur Ordner oder JAR-Dateien hinzufügen. Wenn Sie also eine einzelne Klassendatei haben, müssen Sie diese zuerst in die entsprechende Ordnerstruktur einfügen.

Here ist ein ziemlich hässlicher Hack, der den SystemClassLoader zur Laufzeit erweitert:

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

Die Reflektion ist notwendig, um auf die geschützte Methode addURL zuzugreifen. Dies kann fehlschlagen, wenn ein SecurityManager vorhanden ist.

41
Thilo

Probieren Sie dieses für Größe an.

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

Dadurch wird das Systemklassenladeprogramm so bearbeitet, dass es die angegebene Bibliotheksdatei enthält. Es ist ziemlich hässlich, aber es funktioniert.

37
Chase

Ich habe das mit meinem eigenen Klassenladeprogramm gemacht

URLClassLoader urlClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
DynamicURLClassLoader dynalLoader = new DynamicURLClassLoader(urlClassLoader);

Und erstelle die folgende Klasse:

public class DynamicURLClassLoader extends URLClassLoader {

    public DynamicURLClassLoader(URLClassLoader classLoader) {
        super(classLoader.getURLs());
    }

    @Override
    public void addURL(URL url) {
        super.addURL(url);
    }
}

Funktioniert ohne Reflektion

13
Ranjit Aneesh

Sie können Java.net.URLClassloader mit der URL des Ordners/jar ausprobieren, in dem sich Ihre aktualisierte Klasse befindet, und diesen anstelle des Standardklassenladeprogramms verwenden, wenn Sie einen neuen Thread erstellen.

5
Tobias Schulte

Ja, ich glaube, es ist möglich, aber Sie müssen möglicherweise Ihren eigenen Klassenlader implementieren. Ich habe es nie getan, aber das ist der Weg, den ich wahrscheinlich sehen würde.

0
ssteidl

ja, du kannst. Es muss sich in seiner Paketstruktur in einem vom Rest des kompilierten Codes getrennten Verzeichnis befinden, wenn Sie es isolieren möchten. Sie setzen dann einfach das Basisverzeichnis in der Befehlszeile vor den Klassenpfad.

0
akf