class loader. Mal wieder.

tharo

Mitglied
Hallo erst einmal.

Ich habe dann also nach langem hin und her mich auch mal daran gewagt einen eigenen Class Loader zu entwerfen. Das war einfach höchste Eisenbahn bei dem Umfang meines Projektes.

Der erste Test mit einem Code wie diesem z.B.
Code:
private static Plugin loadPlugin(URL[] locations, String name) 
    	throws InstantiationException, IllegalAccessException, ClassNotFoundException {
    	
    	URLClassLoader classloader = new URLClassLoader(locations, ClassLoader.getSystemClassLoader());
        Class<?> cls = classloader.loadClass(name);

        if (!Plugin.class.isAssignableFrom(cls)) {
            throw new RuntimeException("Invalid class");
        }
        return (Plugin)cls.newInstance();
    }
lief auch absolut problemlos.

Nun wollte ich allerdings mehr als nur ein Plugin pro JAR Archiv haben. Wenn schon denn schon. Also hatte ich den Gedanken mir ein kleines config File (das hier mal nicht Bestand des Problems sein soll) mit in das .JAR archiv zu speichern das mir den classpath der einzelnen Plugins übermittelt. Ab dort sollte alles so funktionieren wie bei oben geposteten Beispiel das man z.B. so aufrufen kann

Code:
File pluginFile = new File("../plugins/test.jar");
URL[] locations = new URL[] {pluginFile.toURL()};

Plugin plugin = loadPlugin(locations, "de.taliis.test.plugin.TestPlugin");

Ich dachte das sollte schon kein Problem darstellen. Ich habe früher ja auch schon immer eifrig Bilder und andere Ressourcen aus JAR Archiven geladen. Wenn auch immer aus dem selben wie jenes in dem auch mein Programm lag.

Code:
URL url = ClassLoader.getSystemResource(path);

Nun ... in diesem Fall will ich ja keine ressource aus dem System Path (oder dem Programm Path) sondern flexibel einfach nur etwas aus dem eingeladenen JAR archiv. Ich benutze also getResource() und nicht getSystemResource().

Da geht das Probem los. Die einzige Ressource in meinem neuen classloader scheint das jar archiv selbst zu sein ..
Was mache ich Falsch?

Code:
		File archive = new File("../plugins/test.jar");
		try {
			classLoader = new URLClassLoader(
							new URL[] {archive.toURL()}, 
							ClassLoader.getSystemClassLoader()
						);			
		} catch (MalformedURLException e) {
			e.printStackTrace();
			return;
		}
		if(classLoader==null) return;
		
		// catch the config file
		URL configURL = classLoader. findResource("./plugins.txt");
		URL alles[] = classLoader.getURLs();
		System.out.println(alles[0].getFile() + alles.lenght);
 
Sie ist null.
Alle files haben eine länge von genau 1 - und dieses file ist das jar archiv selbst. Die im archiv enthaltenen Dateien sind daher nicht "sichtbar" für mich .. Genau das ist das Problem das ich nicht verstehe.
 
Hmm also eigentlich geht das wunderbar:
Java:
public static void main(String[] args) throws Exception {
	URL url = new File("Plugin.jar").toURI().toURL();
	URLClassLoader loader = new URLClassLoader(new URL[]{url});
	final Enumeration<URL> resources = loader.getResources("plugin.txt");
	final InputStream resourceAsStream = loader.getResourceAsStream("plugin.txt");
	System.out.println(resourceAsStream);
	while(resources.hasMoreElements()){
		final URL ul = resources.nextElement();
		System.out.println(ul);
		System.out.println(ul.toExternalForm());
	}
}
 
o_O
Ist logisch das es geht. Das sollte meines nach meinem Verständniss eigentlich auch .. Aber kannst du mir vielleicht sagen wo mein Fehler war?
Ich gebe zu ich komm nicht ganz drauf ..

Vielen Dank auf jeden Fall.
 
Dass du die Rückgabe von getResource nie verwendet hast. Wenn du vom ClassLoader getURLS abrufst nützt dir das gar nichts. Dann kriegst du nur das zurück was du reingesteckt hast. Deswegen weiß ich nicht was diese Zeile da bei dir bewirken sollten.
 
Code:
URL configURL = classLoader.findResource("./plugins.txt");

Ist wie gesagt null.

Selbiges bei getResource usw.
 
Hmja. Sie liegt im root der .jar datei.

Ich habe meinen code nun abgewandelt... hab die URL über das URI object gecastet und direkt den stream geöffnet.

Die Ausgabe ist nach wie vor null ...
So sieht der Code nun aus

Java:
private void load(File archive) {
		// load jar file into our classloader
		try {
			classLoader = new URLClassLoader(
							new URL[] {archive.toURI().toURL()}
						  );			
		} catch (MalformedURLException e) {
			e.printStackTrace();
			return;
		}
		if(classLoader==null) return;
		
		// catch the config file
		InputStream resourceAsStream = classLoader.getResourceAsStream("plugins.txt");
		System.out.println(resourceAsStream);
}
 
So habe dir mal das jar in nem zip angehängt mit welchem ich das gemacht habe.
 

Anhänge

  • Plugin.jar.zip
    1 KB · Aufrufe: 33
Zurück