ClassLoader funktioniert nicht

bnr

Mitglied
Hallo @ all,

ich schlage mich im Moment mit einem ClassLoader rum. Mein Ziel ist es, aus ein Paar jar Dateien mittels Reflection und Anntotation Informationen aus einer bestimmten Klasse auszulesen. Der Code an sich funktioniert ohne Probleme in meinem Projekt (Projekt A). Jedoch verwendet mein Projekt ein eclipse.plugin Projekt (Projekt B) und dann knallt es.

Erst mal ein Paar Code-Schnipsel aus dem Projekt A

Klasse A1
Code:
	ClassLoader cl = Thread.currentThread().getContextClassLoader();
	Method m = URLClassLoader.class.getDeclaredMethod("addURL", new Class[] { URL.class });
	m.setAccessible(true);
	
	for (String title : jarsToBeLoaded.keySet()) {
	    File jarFile = new File(jarsToBeLoaded.get(title));
	    m.invoke(cl, new Object[] { jarFile.toURL() });
	...
	}
...

Aus Klasse B1
Code:
Class instandeDataClass = Class.forName(pluginDS.getInstanceDataClass());

Wenn der Code aus meinem Projekt ausgeführt wird, so ist der ClassLoader cl ein "sun.misc.Launcher$AppClassLoader"
Dieser erbt von URLClassLoader und man kann daher die Methode addURL verwenden.

Wenn jedoch Projekt B den Code in Projekt A verwendet, so handelt es sich um folgenden ClassLoader
"org.eclipse.core.runtime.internal.adaptor.ContextFinder". Die Folge ist, dass es in Zeile m.invoke(cl, new Object[] { jarFile.toURL() }); knallt.

Daher habe ich versucht den ParentLoader von "org.eclipse.core.runtime.internal.adaptor.ContextFinder" zu verwenden (cl=cl.getParent()). Dies ist der "sun.misc.Launcher$AppClassLoader".
Danach läuft der Code in Klasse A1 durch, jedoch kann der Code in Klasse B1 (Class.forName) die Klasse nicht finden (java.lang.ClassNotFoundException).


Ich stehe auf dem Schlauch und habe keinen Ansatz, wie ich dies lösen könnte.
 
Hi,
das gleiche Problem hat ich auch schon mal, ich habe dafür auch noch keine Lösung gefunden. Aber ich kann dir sagen, dass du mit dem ClassLoader nicht Projektübergreifend Dateien laden kannst.
 
Ähm ... WHAT THE ...
Also sowas seh ich ja zum ersten Mal.
Was ich nicht verstehe is warum du extra über Reflections mit dem ClassLoader rumspielst. Die viel einfachere Methode wäre hier einfach einen neuen URLClassLoader mit dem absoluten Pfad auf das zweite Projekt und dann ganz normal über
Java:
Class clazz=urlClassLoader.loadClass("Klasse");
Object o=clazz.newInstance();
die Klasse laden und ein Objekt erzeugen.

Auch sollte der Compiler bei
Java:
File.toURL();
meckern da dies deprecated ist. Statt dessen sollte man
Java:
File.toURI().toURL();
verwenden.
 
So, ich habe jetzt eine Woche versucht den Classloader an den Start zu bekommen, leider ohne Erfolg. Das Problem liegt darin, das Projekt B ein OSGI-Projekt ist. Nun habe ich auch den Code aus Projekt A in Projekt B gelegt, damit ich nur noch ein Projekt habe, ein OSGI-Projekt. Leider ist es mir aber nicht möglich die externen JARS(keine OSGI) zum ClassPath hinzuzufügen, um dann entsprechenden Klassen zu Laden. Hat da jemand eine Idee?
 
Geht auch nicht

URL[] urls = new URL[3];
urls[0] = new URL("...PluginA.jar");
urls[1] = new URL("...PluginB.jar");
urls[2] = new URL("...PluginC.jar");
URLClassLoader cl = new URLClassLoader(urls);
Class instandeDataClass = cl.loadClass("Klasse");

Es hängt mit OSGI zusammen. Die ClassLoader die dort verwendet werden sind OSGI-Classloader vom Framework.
 
Nunja ... wenn du Projekt B als OSGI-Projekt gestaltet hast dann solltest du dies auch über den OSGI-Loader laden.
 
Die Jars sind keine OSGI Bundles. Daher dürfte es mit dem OSGI-BundleLoader nicht funktionieren, oder bin ich falsch Informiert?
 
Hallo,

wo liegen denn die jars, aus denen du die Klassen laden möchtest? Direkt im Filesystem oder innerhalb eines OSGI-Bundles?

Externe jars kannst du auch (wie Spikee) schon angedeutet hat via: URLClassLoader laden
Java:
...
public class Activator implements BundleActivator {
...
	public void start(BundleContext bundleContext) throws Exception {
		Activator.context = bundleContext;
		System.out.println(bundleContext);
		URLClassLoader cl = new URLClassLoader(new URL[]{new File("C:/development/java/libs/guava-r07/guava-r07.jar").toURI().toURL()},Thread.currentThread().getContextClassLoader());
		System.out.println(cl.loadClass("com.google.common.annotations.Beta"));
...

Gruß Tom
 
Hallo,

genau dies funktioniert nicht (java.lang.ClassNotFoundException). Die URL zu der Jar stimmt und die Klasse, die geladen werden soll, ist auch in dem Package bzw. Jar. Wie gesagt, der Loader funktioniert wenn es kein OSGI XTEXT Projekt ist.
 
Zurück