StackOverflowError in XMLEncoder?

Alan47

Mitglied
Hallo zusammen,

ich arbeite derzeit an einem größeren Projekt und stehe grade vor einem Rätsel mit dem XML-Encoder. Hier eine (vereinfachte) Version des Codes (Erklärung gleich danach):

Java:
	public static String encodeToXML(final Object javaObject) {
		// retrieve the jar file containing the neccessary classes
		File jarFile = new File(.....);
		// create the new class loader including the jar
		URL[] loaderURLs = new URL[1];
		try {
			loaderURLs = new URL[] { jarFile.toURI().toURL() };
		} catch (MalformedURLException e) {
			e.printStackTrace();
		}
		URLClassLoader loader = new URLClassLoader(loaderURLs);
		// store the current class loader to re-assign it later on
		ClassLoader currentLoader = Thread.currentThread().getContextClassLoader();
		// assign the new class loader to the thread
		Thread.currentThread().setContextClassLoader(loader);
		// do the conversion to XML
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		XMLEncoder encoder = new XMLEncoder(bos);
		encoder.writeObject(javaObject);
		encoder.close();
		String xmlEncoding = bos.toString();
		try {
			bos.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		// re-assign the former classloader to the thread
		Thread.currentThread().setContextClassLoader(currentLoader);
		// return the XML
		return xmlEncoding;
	}


Was soll die obige Methode machen? Ein Object in XML konvertieren, wobei die Klasse, zu der das Objekt gehört, dynamisch per URLClassloader dazu geladen werden muss. Ich gehe also wie folgt vor:

1) URLClassloader mit der Jar-Datei erzeugen
2) Referenz auf den aktuellen ContextClassLoader des Threads rücksichern
3) ContextClassLoader des aktuellen Threads mit dem neuen URLClassLoader überschreiben
4) Konvertierung zu XML durchführen
5) Dem aktuellen Thread wieder den alten ContextClassLoader zuweisen


Dabei ist das zu konvertierende Objekt wirklich von sehr einfacher Natur, im Wesentlichen enthält es nur einige primitive Felder (hauptsächlich Strings). Trotzdem passiert dann bei "encoder.writeObject(javaObject)" (Zeile 19) folgendes:

java.lang.StackOverflowError
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at com.sun.beans.finder.ClassFinder.findClass(ClassFinder.java:63)
at com.sun.beans.finder.ClassFinder.findClass(ClassFinder.java:105)
at com.sun.beans.finder.ClassFinder.resolveClass(ClassFinder.java:165)
at com.sun.beans.finder.ClassFinder.resolveClass(ClassFinder.java:132)
at java.beans.Statement.invokeInternal(Statement.java:183)
at java.beans.Statement.access$000(Statement.java:56)
at java.beans.Statement$2.run(Statement.java:158)
at java.security.AccessController.doPrivileged(Native Method)
at java.beans.Statement.invoke(Statement.java:154)
at java.beans.Expression.getValue(Expression.java:115)
at java.beans.Encoder.getValue(Encoder.java:105)
at java.beans.Encoder.get(Encoder.java:225)
at java.beans.PersistenceDelegate.writeObject(PersistenceDelegate.java:110)
at java.beans.Encoder.writeObject(Encoder.java:74)
at java.beans.XMLEncoder.writeObject(XMLEncoder.java:274)
at java.beans.Encoder.writeExpression(Encoder.java:304)
at java.beans.XMLEncoder.writeExpression(XMLEncoder.java:389)
at java.beans.PersistenceDelegate.writeObject(PersistenceDelegate.java:113)


... wobei sich die letzten 5 Zeilen des Stacktraces noch einige Male wiederholen, das habe ich jetzt nicht alles kopiert ^^'

In Bezug auf den XMLEncoder wurde überhaupt nichts verändert, also keine Methoden überschrieben etc. es handelt sich wirklich um den Standard XMLEncoder, wie er von Java6 bereitgestellt wird.

Meine Frage ist: hat irgendjemand eine Idee, wie hier diese Endlos-Rekursion zustande gekommen sein könnte? Gibt es einige "übliche Verdächtige", die diesen Fehler auslösen könnten? Ich sitze jetzt schon eine ziemlich lange Zeit an dem Problem, hab das Internet nach Lösungen durchsucht und selber einiges ausprobiert, aber ich finde einfach die Ursache des Problems nicht...


Danke im Voraus,


Alan
 
S

SlaterB

Gast
ClassFinder.findClass usw. sollte kein Problem sein, falls du das mit deinen setContextClassLoader(currentLoader)-Code und Erklärungen vermutest,
dass es dabei letztlich scheitert ist eher Zufall,
wenn die Badewanne randvoll ist kann auch die kleinste Plastikente Wasser überschwappen lassen,

die Wiederholung mit writeObject() usw. deutet naheliegend auf einen Kreis im Objektbaum ab,
du sagst es wäre nur ein einfaches, und stellst es trotzdem nicht zum vollständigen Test zur Verfügung?

was hat letzlich doch der ClassLoader für eine Aufgabe bei dem ganzen?
würde nur mit den Zeilen 17-20 der Fehler genauso auftreten?
 

Alan47

Mitglied
Hallo zusammen,

erstmal danke für den Post an SlaterB. Ich habe von einem Kollegen, der ebenfalls am Projekt beteiligt ist und einmal ein ähnliches Problem hatte, einen hilfreichen Tipp bekommen, der das Problem auch prompt behoben hat. Wenn man nämlich den gleichen (!!) Classloader, der zur Objekterzeugung verwendet wurde, für das XML-Encoding wieder einhängt (anstatt einen neuen, an sich gleichwertigen Classloader zu erzeugen wie in meinem Code im Startpost), dann funktioniert das Encoding fehlerfrei und ohne Exceptions. Zwar bleibt bei mir immer noch die Frage offen, *warum* das so ist, aber wenigstens funktioniert es jetzt problemlos ;)


die Wiederholung mit writeObject() usw. deutet naheliegend auf einen Kreis im Objektbaum ab,
du sagst es wäre nur ein einfaches, und stellst es trotzdem nicht zum vollständigen Test zur Verfügung?

Leider kann ich das nicht - weil ich die Klasse bzw. den Source Code selbst nicht kenne. Es handelt sich hierbei um Klassen, die in unserer Server-Applikation automatisch generiert, compiliert und in eine Jar verpackt wurden und von mir am Client dynamisch geladen werden. Das ganze Umfeld ist enorm komplex, leider ^_^'


Danke für die Hilfe!


Alan
 

Ähnliche Java Themen

Neue Themen


Oben