# Applikation updaten



## SPiKEe (22. August 2010)

moin
gleich vorweg : ich beziehe mich auf folgendes posting
http://www.tutorials.de/enterprise-...-zugriff-auf-den-code-des-hauptprogramms.html
da die letzte frage ... die möglichkeit der updates ... nicht beantwortet wurde und das thema doch schon älter ist wollt ichs jetzt nich noch mal ausgraben sondern der übersicht halber in neues thema machen
*ps : im verlinkten post wurde von Thomas auf weitere postings verwiesen ... der erste ist der den ich mal losgetreten habe ... aber ich habe mich dann für das plugin-system selbst für eine mischung aus meinem und dem geposteten link des thread-erstellers entschieden*

zu meiner frage : ich möchte hier nicht diskutieren wie man nun einzelne plugins komplett unloaded und alle referrenzen entfernt so das GC greifen kann ... nur um dann die einzelene daten zu aktuliesieren ... das ist kein problem für mich
ich würde gerne wissen wie das mit der main-app funktioniert ...

zenario :
main-class > enthält MAIN
GUI-classes
plugin-handler / -manager > für das laden / entladen , die verwaltung und kommunikation zuständig
plugins > im unter-ordner "plugins" in JAR-files

die main-class , die GUI-classes und die plugin-handler befinden sich in einem main-JAR ... *falls hier schon eine aufteilung nützlich wäre bitte erwähnen*

zum ablauf : main-class soll vor laden der GUI ein plugin initialisieren welches für das update des main-JARs zuständig ist ...
damit nun aber das main-JAR aktulisiert werden kann müssen ja alle referrenzen auf alle klassen dieses JARs auf NULL gesetz und durch den garbagecollector freigegeben werden ...
das wäre auch noch kein problem in dem nach der initialisierung des update-plugins ein thread in diesem gestartet wird der die main-class darauf überwacht das alle referrenzen in der main-class aufgehoben wurden ... dann entfernt er seine eigene referrenz auf die main-class und damit sollte das main-JAR nun frei sein *nach einem expliziten aufruf von System.gc(); *ist das an der stelle überhaupt notwendig ?*
da ja nun alle referrenzen auf das main-JAR entfernt wurden sollte es für den update-thread welcher referrenzlos weiterlaufen sollte *ich weis nich ob das wirklich so is* möglich sein das main-JAR zu löschen ... *ich habe es noch nicht ausprobiert ... werde es auch heute abend nicht mehr schaffen ... aber im laufe der nächsten woche dann*

der update-thread soll *BEVOR das main-JAR gelöscht wird* nun das main-JAR via netz auf neue version prüfen , wenn nötig runterladen und "installieren" *im sinne von altes jar löschen und neues einfügen*
nun soll der update-thread wieder eine instanz der main-class bilden und in einer methode einsteigen die NACH dem update liegt *sonst wäre das ein wunderschöner deadlock*
das neu-instanzieren und einspringen an einem gewünschten punkt ist ja nicht das problem

meine frage dazu ist nun eig einfach : ist es möglich das ein JAR sich quasi selbst updatet in dem es über andere JARs und threads geht um alle referrenzen auf sich selbst zu löschen so das es komplett freigegeben und löschbar ist ?
wenn ja : auch so wie ich es oben versucht habe zu beschrieben ?
wenn nein : welche möglichkeiten bleiben ?
eine verwendung von ProcessBuilder bzw Runtime.exec() will ich eigentlich vermeiden ... warum ? ... weil es unter unix z.B. kein JAVAW gibt ... sondern auch für reine GUI-apps ohne console JAVA verwendet wird ...
da ich aber gerne plattformunabhängig bleiben will will ich das ganze mit java-internen mitteln lösen

danke schon mal im vorraus für das zerbrechen eurer köpfe ...

ps : werde wie gesagt mich mal nächste daran versuchen und bei erfolg meinen source posten


----------



## SPiKEe (24. August 2010)

ich habe es jetzt mal mit einer beispiel-implementation versucht ...
ergebnis > der update-thread wartet vergebens auf das freigeben des app.jar und hängt damit in der while fest die zum löschen dient
	
	
	



```
while(!f.delete()) { }
```
ich habe in der app.jar und der darin enthaltenen class alle instanzierten objekte auf NULL gesetzt und anschließend explizit System.gc(); aufgerufen
scheinbar reicht das nicht um das JAR komplett frei zu geben ...
ist es weil der ClassLoader der MAIN noch auf diese zeigt und damit eben nicht alle referrenzen restlos beseitigt werden ?
ich stehe aufm schlauch ...
wäre froh wenn jemand ne lösung hätte ...

ja ... es wäre zwar möglich mit einem dritten davorgeschalteten JAR das ganze zu machen ... aber dann kann ich eben dieses LOADER-JAR wiederum nicht löschen / update ...
gibt es also ne möglichkeit über threads *oder anders* das main-jar komplett freizugeben so dass es gelöscht werden kann ? ... wenn nein : welche problemlösung würdet ihr hier vorschlagen
hilfe , fragen und kritik sind willkommen


----------



## gorefest (25. August 2010)

Hi,

Prüf mal, ob das JarFile in Deinem Classpath liegt. Wenn ja, kannst Du es imo nicht löschen. Einzige Möglichkeit aus Deinem Main heraus einen neuen Classloader zu instantiieren und diesen dann für den eigentlichen Programmstart zu nutzen. Wenn Du per Update Dein altes Jarfile löschen willst, kannst Du das dann tun, weil Du nur noch die Classloaderreferenz löschen musst, um das alte jar zu löschen (hypothese).

Wichtig ist, dass Du keine Referenzen aus Deinem Launcher auf dein Jar hast, ausser über den Classloader und der geholten Klasse.

Grüße
gore

[edit] : da kannst das mit jmap und jhat oder eclipse MAT verifizieren (nach lösen der Classloaderref und gc() dürfen keine jar-only-classes mehr im heapdump herumfliegen).

[edit-2] : du solltest Dir generell Gedanken machen, ob Du wirklich löschen willst, oder einfach eine aktuelle Version Deines JARs installieren möchtest. Moderne Buildwerkzeuge wie maven integrieren per default immer eine Versionsnummer, was das koexistente Vorhalten von JARs unterschiedlicher Version begünstigt.


----------



## SPiKEe (25. August 2010)

danke für die antwort
zu deinen fragen

CP : ja ... JAR liegt im Classpath da dieser bei mir standardmäßig auf
	
	
	



```
CLASSPATH=.;H:\java
```
eingestellt ist ... heißt also das ich erstmal meinen CP ändern müsste damit ich das jar frei bekomme ? wäre umständlich wenn ichs verteile sicherzugehen das nicht bei jemanden dann der CP zufällig ein verzeichnis includierd in den dann das jar gespeichert wird

referrenzen / launcher : ich glaube da hast du etwas missverstanden ...
ich habe deutlich erwähnt das ich KEINEN launcher möchte ...
aus dem grund da ich dann eben genau diesen launcher selbst auch wiederum nicht updaten kann ...
was die referrenzen an sich angeht : natürlich lösch ich die alle und führe GC aus ... und es sind auch alle objekte null ... trotzdem lässt sich das jar nicht löschen

IDE : ich verwende keinerlei IDE's wesshalbe sowas für mich unwichtig ist ...
was die versionierung angeht habe ich bereits ein konzept was co-existenz sicher vermeidet

das mit der instanzierung eines neuen classloader an sich ist sicherlich irgendwie logisch wenn man aus einer klasse komplett aussteigen möchte ... oder verstehe ich hier was falsch ?
könnte es vllt auch daran liegen das ich das über den classloader ein objekt mit newInstance erzeuge welches dann als Thread gecastet und gestartet wird ...
ich mein soweit ich java verstanden habe über die jahre wird doch dann dieser thread als child-thread des main-threads angesehen was das beenden des main-threads unmöglich macht da noch ein child-thread läuft

ich werd es auf jeden fall mal mit dem classpath versuchen ...
sollte sich dadurch nichts ergeben werd ichs noch mal posten ...

ergebnis vom test :
also wenn ich nur den classpath entferne *also einfach übers SET command* kommt es aufs selbe raus als wenn ich aus nem anderen verzeichnis herraus starte *java -jar <path>\app.jar* ... ergebnis bleibt leider das gleiche

das lässt mich zu der annahme kommen das alleine durch den aufruf von java mit angabe des JAR dieses als referrenz im java-internen classloader *also eben dem main-loader* erhalten bleibt

es sei noch mal gesagt : ich möchte auf einen loader / launcher und/oder EXE-wrapper sowie auf den gebraucht von Runtime.exec() / ProcessBuilder verzichten ...
ich dachte halt das es alleine mit THREADS geht ... aber das dem nicht so ist hab ich ja nu festgestellt
hat noch jemand eine idee wie man das MAIN-jar welches man beim aufruf von java angibt und aus dem die app gestartet wird löschen und ersetzen *halt updaten* kann ohne das der eigentlich programmfluss dabei unterbrochen wird *es soll also nicht aus der app ausgestiegen und i-wie neu gestartet sondern mit nur einem aufruf das ganze realisiert werden*

bitte um hilfe und ideen ... und auch hints *wie das man keine jars löschen kann die im CP stehen - thx für die info .. wusste ich noch nicht*

SPiKEe


----------



## gorefest (26. August 2010)

Das mit dem Launcher hast Du wohl missverstanden. Dein Launcher ist eine Minikomponente in einem eigenen Jar-File, welche einen Classloader instantiiert, Dein Applikationsjar nachlädt, die Klasse instantiiert und dann Deine Startroutine auslöst. Dies geschieht alles in der selben JVM und Du brauchst keinen ProcessBuilder, Threads o.ä..

Was Du bedenken musst, ist die Tatsache, dass Dein root classloader samt main() läuft und damit Referenzen in Dein Jar-File hält, womit dieses Jar-File nicht löschbar ist.

Es geht hierbei weniger um den Classpath, sondern viel mehr um die Tatsache, dass das Jar benutzt wird und demnach nicht überschrieben werden kann.

Dabei hilft Dir auch nicht die Tatsache, dass Du keine Objekte mehr hältst, da die im Jarfile enthaltenden Klassendefinitionen im aktiven Classloader verbleiben (Heap vs Perm)


Grüße
gore


----------



## SPiKEe (26. August 2010)

aaah ... das ist doch mal ne antwort die mich endlich schlauer macht und mich meiner lösung näher bring





> Was Du bedenken musst, ist die Tatsache, dass Dein root classloader samt main() läuft und damit Referenzen in Dein Jar-File hält, womit dieses Jar-File nicht löschbar ist.


genau das wollte ich doch wissen ...
ich hatte so etwas schon vermutet war mir aber nicht sicher ...
was meine aussage über die thread - child-thread - theorie angeht > SCHWACHSINN ... man kann threads aus einem anderen heraus starten ... diese laufen dann unabhängig von ein ander *nur als info für alle die es NICHT wussten*

das mit dem loader ist wie gesagt immo der streipunkt zwischen uns beiden ...
WAS du damit meintest war mir klar ... ich wollte dir lediglich zu verstehen geben das ich genau so etwas eigentlich vermeiden wollte aus dem grund da ja dann eben genau dieser loader wiederum nicht updatebar ist *halt aus den gründen mit dem root-classloader und so*
aber wie es aussieht werde ich wohl um genau diesen loader nicht herrum kommen ... dann muss ich das ganze halt so für den RC basteln das ich auch noch in jahren dieses konzept nicht verändern werde ( / muss)

ich danke dir hiermit noch mal für die info und die eindeutige ... nicht missverständliche antwort ...


PROBLEM GELöST > THREAD ERLEDiGT
*kann ~closed~ wenn ihr wollt*


----------



## SPiKEe (26. August 2010)

PROBLEM NOCH NICHT GELÖST


so .. habe mir jetzt einen loader zusammen geschustert der das jar-file über einen URLClassLoader läd ... das class-object erzeugt ... dann noch ein object über newInstance() und dann über reflections die mehtod startet welche den updater starten soll
das funktioniert auch so weit und der thread im updater wird gestartet und die methoden returnen alle ...
danach werden alle referenzen auf NULL gesetzen ... GC aufgerufen ... und trotzdem bleibt der thread des updaters immer noch am löschen des files hängen ... obwohl auf dieses keinerlei referenzen mehr bestehen ...

entweder ist der aufruf über reflections das problem ... oder ich steh total aufm schlauch

n beispiel wäre nett ...

schema :
launcher > launcher.jar > läd app.jar
app > app.jar > läd im construtor *in launcher über newInstance* den pfad um diesen für den CL des updaters zu verwenden* > über public void update() den updater-thread starten *bis hierhin ****t auch alles*
updater > updater.jar > soll lediglich die app.jar löschen und das file app.new in app.jar umbennen .. dieses dann über einen URLClassLoader laden und dann in app *vorher newInstance* einen Thread starten *also newInstance muss auf Thread gecastet werden*

habe es soweit alles lauffähig ... nur hängt er beim löschen von app.jar

CODES :
launcher

```
import java.io.*;
import java.net.*;
import java.lang.reflect.*;
public class launcher
{
	public static void main(String[] args) throws Exception
	{
		String _PATH=(new File(System.getProperty("java.class.path"))).getCanonicalFile().getParent();
		File uf=new File(_PATH, "app.jar");
		URI uri=uf.toURI();
		URL url=uri.toURL();
		URL[] urla=new URL[] { url };
		ClassLoader cl=new URLClassLoader(urla);
		Class<?> clazz=cl.loadClass("app");
		Object oi=clazz.newInstance();
		Method[] ma=clazz.getMethods();
		for(Method m : ma)
		{
			if(m.getName().equals("bootstrap"))
			{
				m.invoke(oi);
				System.out.println("bootstrap invoked");
				m=null;
				break;
			}
		}
		oi=null;
		ma=null;
		uf=null;
		uri=null;
		url=null;
		urla=null;
		cl=null;
		clazz=null;
		_PATH=null;
	}
}
```

app

```
import java.io.*;
import java.net.*;
public class app extends Thread
{
	String _PATH="";
	public app() throws Exception
	{
		_PATH=(new File(System.getProperty("java.class.path"))).getCanonicalFile().getParent();
	}
	public void bootstrap() throws Exception
	{
		System.out.println("start bootstrap");
		File uf=new File(_PATH, "updater.jar");
		URI uri=uf.toURI();
		URL url=uri.toURL();
		URL[] urla=new URL[] { url };
		ClassLoader cl=new URLClassLoader(urla);
		Class<?> clazz=cl.loadClass("updater");
		Thread oi=((Class<Thread>)clazz).newInstance();
		System.out.print("start updater ... ");
		oi.start();
		System.out.println("ok");
		uf=null;
		uri=null;
		url=null;
		urla=null;
		cl=null;
		clazz=null;
		oi=null;
		_PATH=null;
	}
	public void run()
	{
		System.out.println("RUNNING v1");
	}
}
```

updater

```
import java.io.*;
import java.net.*;
public class updater extends Thread
{
	String _PATH="";
	public updater() throws Exception
	{
		_PATH=(new File(System.getProperty("java.class.path"))).getCanonicalFile().getParent();
	}
	public void run()
	{
		try
		{
			File of=new File(_PATH, "app.jar");
			File nf=new File(_PATH, "app.new");
			System.out.print("wait for delete ... ");
			while(!of.delete()) { }
			System.out.println("ok");
			of=null;
			nf.renameTo(new File(_PATH, "app.jar"));
			nf=null;
			ClassLoader cl=new URLClassLoader(new URL[] { (new File(_PATH, "app.jar")).toURI().toURL() } );
			Class<?> clazz=cl.loadClass("app");
			Thread oi=((Class<Thread>)clazz).newInstance();
			oi.start();
			cl=null;
			clazz=null;
			oi=null;
			_PATH=null;
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}
}
```

ich weis ... _PATH sieht schlimm aus ... ist aber so der einzige weg den ich jetzt so ausm stand hab der zuverlässig den pfad zum file bestimmt um ihn im URLClassLoader zu verwenden ... wenn das eleganter geht bin ich für ne lösung offen


----------



## SPiKEe (26. August 2010)

neue erkenntnisse

da ich ja das Java7-ea benutze steht mir in java.net.URLClassLoader die methode public void close(); zur verfügung ...
dies wird allerdings über sun.misc.URLClassPath realisiert ...
und das ist schon wieder ein grund diese technik nicht zu verwenden *wir alle wissen welch nachteile klassen aus den paketen sun.* bringen KöNNEN*
laut Thomas ermöglicht dies das implizite schließen von gelockten daten ...
naja habs ausprobiert und BAM ... es hat sofort ge****t *mit dem code oben* ...
nun stellt sich für mich die frage : wie nun also das gelockte app.jar explizit freigeben damit der lock rausfällt und das file gelöscht werden kann ? ...
ich möchte das ganze dann eigentlich unter J5.0 / J6 laufbar machen *warum J5.0 .. weil es immer noch leute gibt die J5.0 oder sogar noch älter *J1.4.x* aufm rechner haben ...
auf die J1.4.x-user nehme ich keine rücksicht da es J5.0 und J6 bereits lange genug gibt und mitlerweile jeder geupdated haben sollte ...
jedoch möchte ich meine user nicht dazu nötigen sich das *atm noch recht verbuggte* J7-ea laden zu müssen ... ich selber erlebe immer wieder die besten crashes damit ...

meine frage ändert sich also nun in so fern : wie kann man die durch den URLClassLoader gelockten files explizit freigeben wenn ein bloßes NULL-setzen des URLClassLoaders und der referenzen nicht ausreicht ?
gibt es da vllt wieder so einen denk-um-6-ecken - trick ? ...

bin für alle arten von antworten offen

SPiKEe


----------



## Akeshihiro (26. August 2010)

Warum lädst du über den Launcher zuerst die App anstatt den Updater? Das ergibt doch null Sinn. Erst Updater, der schaut, ob ein Update nötig ist, und dann erst die App starten oder halt zuerst das Update ziehen und dann die App starten. Lass die app.jar einfach in Ruhe solange nicht klar ist, ob sie gestartet oder ersetzt werden muss.


----------



## SPiKEe (27. August 2010)

das mit dem "app.jar zu erst laden" entstand ja aus der idee herraus das ich keinen launcher brauchen würde / nicht haben wollte
ich habe jetzt allerdings über reflections n weg gefunden der es mir ermöglichen SOLLTE auf den launcher zu verzichten ... werde das ganze aber erst übers wochenende mal versuchen so zusammen zuzimmern ...
laut java bug-reports soll es schon leute gegeben haben die dieses problem zu zeiten des 1.3 genervt haben soll und die sich dann ClassLoader.close() selbst implementiert haben *nach dem was da so steht kann man das ganze schon mit java.lang.ClassLoader machen und nicht erst mit URLClassLoader und sub-klassen
natürlich hast du so gesehen völlig recht ... und das updaten der updater.jar würde ich dann im launcher einbauen ... aber werde vorher noch mal den weg mit reflections versuchen

SPiKEe


----------



## Akeshihiro (27. August 2010)

Na dann bin ich mal über deine Lösung gespannt ^^ Ich habe es zwar noch nicht gebraucht, aber wer weiß, es gibt immer ein erstes Mal ^^


----------



## gorefest (27. August 2010)

> laut java bug-reports soll es schon leute gegeben haben die dieses problem...



*lol* du bist dir aber schon im klaren, das JEDER applicationserver genau diese funktionalitäten fehlerfrei bieten muss?

Ich würde mal eher auf ein Layer8-Problem tippen ;-)

Du darfst im übrigen GAR keine referenzen auf ein innerhalb deines Jars typisierten Objekte halten. 

Sonst hängt der Rest Deines Jars immer noch im PermGen.


```
oi.start();
            cl=null;
            clazz=null;
            oi=null;
            _PATH=null;
```

wer beendet Deinen Thread? Btw, Du bist Dir aber schon im klaren, dass Du mit der Übergabe Deiner (anonymen) Klasse an den Thread wieder eine Verquickung zwischen den Classloadern schaffst, ne?

Wozu brauchst Du überhaupt einen Thread?

btw, ich gebe Dir noch die Empfehlung, Dich an die Java Coding Standards zu halten, aber das muss jeder selbst wissen ;-)


----------



## Thomas Darimont (27. August 2010)

Hallo,

willst du deine Anwendung im laufenden Betrieb updaten können, oder darf das Update auch nach einem Neustart passieren? Sprich beim Start der Anwendung prüft dein System auf ein Update. Liegt eines vor wird dies im Hintergrund geladen. Sobald die Update Dateien komplett vorliegen fragt die Anwendung nach einem Neustart. Beim nächsten Start wird dann das Update automatisch ausgeführt in dem die entsprechenden jars mit den neueren Versionen überschrieben und anschließend dynamisch mit einem URLClassLoader in den Classpath gelegt werden (vorher von den alten Jars zur Sicherheit noch ein backup anlegen damit bei einem Fehler das "letzte" System wieder hergestellt werden kann.) 

Weiterhin wäre eine Frage ob deine Plugins selbst auch wieder von anderen Plugins abhängig sein dürfen. Das würde einen robusten Update Mechanismus noch etwas komplexer machen.

Gruß Tom


----------



## SPiKEe (27. August 2010)

@gorefest
der Layer-8-error liegt grade bei dir ... denn du hast es offenbar nicht GENAU gelesen
1) lies mal die alten *ober auch aktuellen* bug-reports ... da siehst du das es genug gibt die auch über solche probleme bei application-servern schreiben .. hier hauptsächlich auf windows begrenzt
2) ich habe euch mitgeteilt das es mit Java7 ****t da in dieser version von URLClassLoader das interface Cloasable implementiert wird was rekursiv alle file-locks explizit aufhebt ... ansonsten habe ich am restlichen code NICHTS verändert und es hat funktioniert ... gegen-frage also : wo siehst du hier probleme wenn es doch auch so geht
3) welche java coding standards meinst du bitte ? ... bezeichnungen ? ... aufrufe ? ... schreibweisen ? ...
es tut mir leid .. aber ich konnte in meinen bisherigen codes nie nachteile gegenüber "sauber" implementierten codes erkennen ... es kam sogar öfter vor das von der performance meine codes weit vorne lagen im gegensatz zu den "optimierten" ... von daher : jedem das seine ...

@Thomas
ach mensch Thomas ... ich weis was du jetzt denkst ...
ich habe es dir schon in meinem plugin-thread gesagt : für meine anforderungen denkst du zu produktiv ...
wenn das ganze dann mal etwas pupolärer wird und ich hilfe bei optimierung oder struktur-planung brauche kann ich dich ja sicher noch mal fragen ... aber zur zeit kann ich deine posts nicht nutzbringend verwende


wie dem auch sei ...
ich werde übers WE mal ne VM aufsetzen mit unix und win und mal mit J5.0 versuchen das ganze i-wie zu implementieren *mit reflections halt* ...
wenn es so geht wie ich mir das denke brauch ich nicht mal einen neuen URLClassLoader sondern kann den root-CL dierekt manipulieren ...
aber das werd ich frühestens morgen abend wissen wenn ichs mal implementiert hab

trotzdem dank an alle die sich hierrüber den kopf zerbrochen haben ...
wenn ich eine passende lösung gefunden habe werd ich sie posten das auch andere vllt was von haben


----------



## SPiKEe (29. August 2010)

so .. um hier jetzt mal den schlusstrich zu ziehen

es ist nicht möglich mit einer 2-jar - konfikugration das root-jar mit hilfe des zweitens jars zu updaten
auch ein manipulieren des root-classloaders mit reflections hilft da nicht viel weiter da im besten fall die VM mit einem FATAL ERROR aussteigt
von daher muss man einen launcher verwenden der den root-classloader auf sich zieht und die anderen jars mit hilfe des URLClassLoaders läd

was das hot-pluggable von plugins angeht
ab java7 implementiert URLClassLoader das interface Closeable womit da explizite freigeben von gelockten jars möglich wird ...
um dies auch in älteren versionen nutzen zu können muss man von URLClassLoader eine eigene klasse ableiten die das interface Closeable implementiert und dann close() mit reflections vollstopfen um an die jar-files zu kommen
das ganze sollte dann so aussehen

CustomURLClassLoader.java

```
import java.io.*;
import java.net.*;
import java.util.*;
import java.util.jar.*;
import sun.misc.*;
import java.lang.reflect.*;
public class CustomURLClassLoader extends URLClassLoader implements Closeable
{
	public CustomURLClassLoader(URL[] url)
	{
		super(url);
	}
	public void close()
	{
		try
		{
			Class clazz=java.net.URLClassLoader.class;
			Field ucp=clazz.getDeclaredField("ucp");
			ucp.setAccessible(true);
			Object sun_misc_URLClassPath=ucp.get(this);
			Field loaders=sun_misc_URLClassPath.getClass().getDeclaredField("loaders");
			loaders.setAccessible(true);
			Object java_util_Collection=loaders.get(sun_misc_URLClassPath);
			for(Object sun_misc_URLClassPath_JarLoader : ((Collection) java_util_Collection).toArray())
			{
				try
				{
					Field loader=sun_misc_URLClassPath_JarLoader.getClass().getDeclaredField("jar");
					loader.setAccessible(true);
					Object java_util_jar_JarFile=loader.get(sun_misc_URLClassPath_JarLoader);
					((JarFile) java_util_jar_JarFile).close();
				}
				catch (Throwable t)
				{
					// if we got this far, this is probably not a JAR loader so skip it
				}
			}
		}
		catch (Throwable t)
		{
			// probably not a SUN VM
		}
		return;
	}
}
```

> NICHT GETESTET ... nur aus bugs.sun.com kopiert

ich hoffe ich kann einigen die das hier im nachhinein lesen damit helfen

danke an alle die an diesem thread mitgeschrieben haben ...

THREAD ERLEDiGT !

SPiKEe


----------

