• Apfeltalk ändert einen Teil seiner Allgemeinen Geschäftsbedingungen (AGB), das Löschen von Useraccounts betreffend.
    Näheres könnt Ihr hier nachlesen: AGB-Änderung
  • Was gibt es Schöneres als den Mai draußen in der Natur mit allen Sinnen zu genießen? Lasst uns teilhaben an Euren Erlebnissen und macht mit beim Thema des Monats Da blüht uns was! ---> Klick

URLClassLoader - Klassen aus jar-Archiven laden

  • Ersteller nocxsville
  • Erstellt am

nocxsville

Gast
Hi ich habe folgendes Problem:
Ich möchte eine Klasse aus einem jar-Archiv laden (bzw. ein Objekt davon erzeugen). Mein bisheriger (vereinfachter) Code sieht so aus:

import java.net.URL;
import java.net.URLClassLoader;
import myapp.MyPlugin;

public class Main {

public static void main(String[] args) throws Exception {
URL [] urls = {new URL("file://K:/myapp/plugin/foo.jar")};
ClassLoader classLoader = new URLClassLoader(urls, Thread.currentThread().getContextClassLoader());

MyPlugin plug = (MyPlugin) classLoader.loadClass("myapp.plugin.TestPlugin").newInstance();
}
}

So wie es momentan implementiert ist läd der URLClassLoader die Klasse TestPlugin, die sich in dem Verzeichnis "file://K:/myapp/plugin/" befindet, jedoch nicht (wie ursprünglich gewollt) die Klasse "TestPlugin" aus meinem jar-Archiv. Kann mir einer erklären, wie ich auf Klassen innerhalb eines jar-Archivs zugreifen kann oder noch besser was ich an diesem Code verändern muss, damit es klappt?

THX
 

commander

Baldwins roter Pepping
Unvergessen
Registriert
25.02.04
Beiträge
3.206
Langsam mit den jungen Pferden ;)

Sag mir mal, ob diese Annahmen korrekt sind:

  • MyPlugin ist ein Interface (und sollte demnach z.B. MyPluginIF heissen - nicht unbedingt notwendig, aber erhöht die Lesbarkeit enorm)
  • Du willst, dass der ClassLoader die Klasse "TestPlugin" aus foo.jar lädt?
  • Eine andere Klasse namens "TestPlugin" liegt ebenfalls unter dem angebenen Verzeichnis "myapp/plugins/"?

Abgesehen davon, dass Du absolute Windowspfade angibst (pfui! _immer_ relativ angeben!), ist es für den URLClassloader (falls ich Deine Konstruktion ohne weiterführende Infos verstehe) nicht möglich, die gewünschte Klasse zu finden, da Du einen ParentClassloader angibst, der im Defaultfall _immer_ zuerst befragt wird, ob er die Klasse bereits kennt. Falls das der Fall ist, wird diese bereits bekannte Klasse zurückgegeben.

D.h., wenn durch einen import o.ä. 'TestPlugin' aus dem normalen Klassenpfad bereits dem SystemClassLoader (und das ist im einfachen Falle der Parent) bekannt ist, dann wird der URLClassLoader einfach garnichts machen, ausser die bereits gefundene Klasse des SystemCL zurückzugeben.

Bereits ein statischer Zugriff auf eine Klasse mit den entsprechenden Importstatment wird dazu führen, dass der System-Classloader einfach die erstbeste Klasse im Klassenpfad lädt - und das wars für Dich. Das ist im Normalfall sehr sinnvoll, aber eben nicht immer.

Beschreibe doch mal, was Du eigentlich machen willst, vielleicht findet sich ja eine sehr viel einfachere Lösung. ;)

Gruß,

.commander
 
Zuletzt bearbeitet:

nocxsville

Gast
Hi commander, danke erst mal für die schnell Antwort.:)

Also ursprünglich hatte ich vor einen PluginManager zu schreiben, dem man als String den Dateinamen eines jar-Archives übergibt und der dann aus diesem Archiv die Klasse "Start" läd (die die abstracte Klasse "MyPlugIn" erweitert) und diese dann zurückgibt.

Ich habe einen Ordner "plugins" in dem alle Plugins als jar-Archiv liegen.
In meinem Beispiel liegt auch eine Klasse Names "TestPlugIn" in dem "plugins"-Ordner, diese sollte der URLClassLoader jedoch ignorieren, da er sich ja nur um die jar-Archive kümmern soll. Dein Einwand mit dem "SystemClassLoader" klingt aber plausibel und erklärt so einiges

P.S.: Das ich einen absoluten Pfad angegeben habe liegt da dran das ich das Beispiel so einfach wie möglich halten wollte.
 

commander

Baldwins roter Pepping
Unvergessen
Registriert
25.02.04
Beiträge
3.206
Cool, wie lange javast Du schon? An Classloader wagen sich viele Entwickler erst nach Jahren.

Gruß,

.commander
 

nocxsville

Gast
Öhm javaern tue ich schon seit mehr als 3 jahren, programmieren schon länger...ich versuche mir neben dem studium einiges selber bei zu bringen und hab einige projekte am laufen, weil das was wir im studium lernen reicht bei weiten nicht um später damit geld zu verdienen.

Also ist das nicht so einfach Klassen aus einer jar zu laden? Im prinzip dürfte das ja nicht viel schwerer sein als Klassen zu laden die irgendwo im file-system liegen...aber irgendwie hab ich den letzten fehlenden kniff noch nicht gefunden...irgendwo hab ich auch mal was gelsen das man in dem String ein "!" einfügen muss und alles was nach dem "!" kommt im jar-Archiv liegt. In der URLClassLoader Doku steht das wenn der URL String mit ienem "/" endet der Loader von einem Verzeichnis aus geht ansonsten von einem jar-Archiv.

Wär cool wenn du mir einen Lösungsansatz posten könntest oder mir sagst was ich an meinen kleinen Beispiel vom Anfang ändern muss...
THX
 

commander

Baldwins roter Pepping
Unvergessen
Registriert
25.02.04
Beiträge
3.206
Hi Du,

hab Dir ein kleines Projekt hochgeladen, dass genau das macht, was Du willst.

4 Sourcefiles: Main, MeinInterfaceIF, Impl1 und Impl2.

In classes/ liegt nur Main, MeinInterface, Impl1
Im Verzeichniss libext/ (das nicht in den Klassenpfad kommt) liegt ein jar, in dem sich Impl2 befindet.

Impl1 und Impl2 geben jeweils in der Methode tellMeWhoYouAre() "Nummer 1" oder "Nummer 2" aus.

Wenn Du nun im Verzeichnis ovberhalb von classes stehst und mit "java -cp classes/ Main" das Programm ausführst, dann wirst Du sehen, dass auch Impl2 geladen wird, obwohl es nicht im Klassenpfad liegt.

Gruß,

.commander
 

Anhänge

  • URLS.zip
    14,1 KB · Aufrufe: 1.341

nocxsville

Gast
Hey THX ich werds nachher gleich mal ausprobieren :)
 

docGoe

Gast
Hi commander,

mit einem ähnlichen Problem wie nocxsville bin ich hier auf euren thread gestoßen und deine Antwort hat mir auch echt weitergeholfen, aber bist du sicher, daß du den ParentClassloader in deiner main()-Methode umgehst? Die API docu klingt leider anders:
"Constructs a new URLClassLoader for the specified URLs using the default delegation parent ClassLoader. The URLs will be searched in the order specified for classes and resources after first searching in the parent class loader."

Gruß
docGoe

P. S.: Euer JWheel project klingt echt interessant.