Update einer Jar während der Laufzeit

Xeonkryptos

Bekanntes Mitglied
Ich weiß, dass das Thema schon oft angesprochen und erklärt wurde und die SF von dem Forum, sowie google hab ich schon verwendet, aber dennoch komme ich nicht weiter...

Ich habe ein Programm, welches ich natürlich ab und an mal eine Aktualisierung unterziehe, ich aber keine Lust habe, meinen Bekannten/Freunden, die das Programm nutzen, immer wieder die neue jar-Datei zu schicken. Nun hätte ich gerne eine Update-Funktion geschrieben, wodurch ich das Programm während der Laufzeit aktualisiere und alle neuen Funktionen OHNE einen Neustart nutzbar machen möchte. Das dieses geht, ist mir bewusst, aber ich hab das Problem in der Umsetzung.
Ich lasse mein Programm auf einen Server zugreifen auf dem sich eine Textdatei befindet, worin steht, welche Versionsnummer momentan die aktuellste ist und die mit der vom Programm verglichen wird, ist die Versionsnummer in der txt-Datei höher, verbindet das Programm sich mit einem Server und lädt die aktuellste Datei herunter (die aktuelle Datei liegt im selben Pfad wie der Server). Das funktioniert soweit ganz gut. Diese landet dann auch ohne Probleme auf der Platte des Rechners. (Ist eine jar-Datei die geladen wird!)

Nun möchte ich die Klassen aus dem neuen jar in die momentan laufende Anwendung einbauen/laden und die neuen Funktionen nutzbar machen. Auch soll dann zum Beispiel die Versionsnummer erhöht werden, die sich in einer Config-Klasse befindet, aktualisiert werden.

Nun habe ich, wie schon oben erwähnt, viel recherchiert und weiß, dass ich die Klassen neu laden muss, am besten über einen eigenen Classloader bzw den URLClassLoader, um die alten zu ersetzen. Nun leitet der URLClassLoader die Anfrage erst an den ClassLoader, der schon meine Anwendung geladen hat weiter und es wird die Klasse nicht neu geladen. Mein Ziel ist es, dieselben Klassen mit der selben Package-Struktur aus der neuen Jar zu laden und die alten zu "ignorieren", damit der ClassLoader vom GC weggeräumt werden kann, doch kriege ich das nicht hin.

Mein Ansatz:
Java:
ClassLoader loader = null;
		try {
			loader = URLClassLoader.newInstance(new URL[] { new File(
					Config.FILE_PLACE2).toURI().toURL() });
		} catch (MalformedURLException e) {
			e.printStackTrace();
		}
		Class<?> c = null;
		try {
			c = loader.loadClass("client.core.Main");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		try {
			c.newInstance();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}

Hier habe ich es testweise erstmal mit einer einzigen Klasse versucht, die auch gefunden wird, aber nicht geladen wird, da diese schon im Parent-ClassLoader vorhanden ist und ich diesen leider nicht umgehen kann, zumindest mir nicht bewusst wie.
Es hieß immer, ich müsse einen neuen ClassLoader instanzieren und die neuen Klassen laden, sodass dadurch im Endeffekt die Referenz zum anderen ClassLoader "verloren" geht und der GC diesen wegräumt. Auch hieß es überall, dass die neu geladenen Klassen durch einen neuen ClassLoader einzigartig sind, dass heißt, dass diese auch im Parent-ClassLoader vorhanden sein können, ohne das Probleme auftreten.
Genau hier fängt mein Problem an. Ich müsste den Parent-ClassLoader umgehen oder zumindest meinen eigenen ClassLoader trotz der schon geladenen Klasse die Klasse neu laden können.

Weiterhin würde ich dann gerne wissen, wie ich es am schönsten schaffe, wenn alle Klassen neu geladen sind, OHNE ein Neustart der JVM, wie ich die GUI dann darauf aufmerksam mache, dass es sich mal aktualisieren/anpassen soll. Mir ist die Methode validate() bekannt, nur hat die neu geladene Klasse denn auch die gleiche Referenz auf dasselbe schon offene Fenster? Ich meine mal nicht.

Zumindest ist mir der obere Teil erstmal wichtiger und ich hoffe, ihr könnt mir helfen.
 
N

nillehammer

Gast
Hallo Xeonkryptos,
Du hast Dich wahrscheinlich schon intensiv mit dem Thema auseinandergesetzt. Ich nicht so :oops: Aber vielleicht hilft Dir der Hinweis auf die Methode newInstance, bei der man den parent class loader als Parameter mitgeben kann. Der kann sogar null sein. Damit hast Du einen, der nicht zu dem delegiert, der Deine Klassen schon geladen hat. Ich habe mal etwas Testcode geschrieben und es damit hinbekommen, mehrere Male die selbe Klasse zu laden:
Java:
package test;

import java.net.URL;
import java.net.URLClassLoader;

public class Test {

	public static void main(final String[] args ) throws Exception {
		
		final URL[] urls = { new URL("file:///home/nille/projects/TestProject/bin/") };

		final ClassLoader withParent = URLClassLoader.newInstance(urls);

		final Class<?> firstWith = withParent.loadClass("test.Test");
		
		System.out.println(firstWith==Test.class);
		
		final ClassLoader withoutParent = URLClassLoader.newInstance(urls, null);
		
		final Class<?> firstWithout = withoutParent.loadClass("test.Test");
		
		final Class<?> secondWithout = withoutParent.loadClass("test.Test");
		
		System.out.println(firstWith == firstWithout);
		
		System.out.println(firstWithout == secondWithout);
	}
}
Pfadnamen, Packages und Klassen musst Du natürich anpassen. Aber das Prinzip dürfte klar sein.
 

Xeonkryptos

Bekanntes Mitglied
Danke für den Hinweis, das werde ich mal in angriff nehmen... Darauf hätte ich auch selber kommen können, aber wie immer sehe ich die Feinheiten immer dann, wenn ich schon längst am verzweifeln bin. :D

Das kommt davon, wenn man sich auf den ClassLoader fixiert und sich nur auf die eine Methode verharrt. =) ... schlimm ist aber auch, dass es überall heißt, man soll genau das machen, wie ich beschrieben hab, diese aber in Codebeispielen immer die einfache newInstance() verwenden. :(
 

Xeonkryptos

Bekanntes Mitglied
Okay... jetzt hab ich meinen Fehler eingesehen^^ Ich hab außer acht gelassen, dass ich den parent-classloader auch mit null beziffern kann. :) :oops:

Edit: Jetzt hab ich aber noch die offene Fragen, wie schon oben erwähnt: Wie schaffe ich das nun, dass das Frame mit aktualisiert wird, nachdem ich alle Klassen neu geladen hab bzw die Frame-Klasse?

Für mich besteht das Problem, dass das Frame-Objekt nicht die neu geladene Klasse kennt bzw das Objekt in der Klasse nicht die Referenz zu dieser Klasse besitzt. Mit validate() komme ich hier nicht weiter, wenn ich richtig liegen sollte. Muss ich das Frame erst disposen und dann mit der neuen Klasse instanzieren oder gibt es einen schöneren Weg? Da ich das alles in einem Chat verwende, sollte der Verlauf jetzt nicht gelöscht werden oder andere Dinge, da ich diese noch nicht auf die Festplatte schreiben lassen möchte.
 
Zuletzt bearbeitet:

FArt

Top Contributor
Du erfindest das Rad zum x-ten mal neu.

Es gibt schon viele Classloader Implementierungen, die so etwas können. Ein gutes Beispiel ist der ANT Classloader, der mit isolierten Klassenpfaden und parent-last delegation konfiguriert werden kann. Das Thema ist alles andere als trivial und der Teufel steckt im Detail, z.B. was machst du mit alten Intanzen der Klassen, die plötzlich ersetzt werden? Passen die immer mit den neuen Klassen zusammen?
An diesen Themen haben sich große Tools und APIs lange Zeit die Zähne ausgebissen.

Ich habe mal gelesen, dass JBoss seine Classloading in eine API gegossen hat, die man auch in eigenen Applikationen verwenden kann. Guck mal danach (evlt. 9.2.*ClassLoading ).

Frage: warum kann man nicht einfach einen Neustart machen, wenn die neue Version heruntergeladen wurde? Damit entledigst du dich aller Probleme...

... oder nimm OSGi...
 

Xeonkryptos

Bekanntes Mitglied
Ich sehe ein, dass es irgendwann zu schwer werden wird. Zu Anfang kann ich noch sagen, dass andere Klassen alle die neuen Klassen verwenden können, weil ich veränderte Klassen einfach neu geladen hätte, aber irgendwann wäre das wohl zu viel geworden, weil ich das auch erweitern möchte.
Ich versuche mich jetzt mit dem OSGi-Framework und möchte da gleich mal fragen, ob es da irgendein Tutorial gibt, welches ihr als gut empfunden habt und weiterempfehlen könnt? Für einen Einstieg mit dem Framework.

@FArt: Ich möchte einen Neustart verhindern, weil ich das ansonsten auf ein Script oder ein anderen Programm, welches nicht in Java geschrieben ist, auslagern müsste. Wieso soll man auch die Möglichkeit außen vor lassen mit dem Neuladen von Klassen und diese benutzen (Plug-In-Verhalten), wenn mir Java dieses bietet und ich daran lernen kann? Es mag zwar komplizierter sein, aber irgendwo muss es auch Herausforderungen geben. :)
Außerdem ist das Neustarten ein nerviges Unterfangen mit seinen Vorteilen, ja, aber wenn ich es umgehen kann, wieso nicht? Ich verlange ja keinen fertigen Code ohne, dass ich irgendeinen Ansatz gebracht habe!
 

Andreas29

Bekanntes Mitglied
Hi,

schau dir mal Java Web Start an, dass müsste genau das richtige für dein Problem sein. Damit kann sich dein Programm während des Startens zu einem Server verbinden und prüfen, ob eine Aktualisierung durchzuführen ist. Weiterhin kannst du es für die Verbreitung deines Programmes wunderbar nutzen, weil zur Installation lediglich ein Link angeklickt werden muss. Alles weitere passiert dann automatisch.

Grüße,
Andreas
 

Xeonkryptos

Bekanntes Mitglied
Ich bin mir bewusst, dass es WebStart gibt, ich möchte dieses aber erstmal nicht nutzen. Mein Programm dient mir auch zum Üben und da mach ich so viel ich kann lieber selbst. :)
 
B

bygones

Gast
Neustart ist der beste weg, der user kennt das von anderen programmen. Notfalls sagen "programm muss neugestartet werden...."
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
T Java 8 Security Update Allgemeine Java-Themen 3
krgewb Darstellung bei Java-Update Allgemeine Java-Themen 8
VfL_Freak Große und seltsame Probleme nach Java-Update auf V1.8.0_91 Allgemeine Java-Themen 3
B Umgebungsvariable Anpassen der Umgebungsvariablen nach Java-Update ? Allgemeine Java-Themen 14
S Java-Webstart und Update-Checks Allgemeine Java-Themen 0
A Update Software programmieren Allgemeine Java-Themen 1
T Nach Java Update: Jar Datein öffnen sich nicht mehr mit doppelklick Allgemeine Java-Themen 3
G JavaFX Problem nach Update auf Java 8 Allgemeine Java-Themen 0
E Java 7 update 51 Allgemeine Java-Themen 9
H SHA256 update-Funktion Allgemeine Java-Themen 3
F.S.WhiTeY JDK installieren Linux: Nach Update link auf Java zerschossen Allgemeine Java-Themen 4
eskimo328 Swing Client Anwendung für MAC OS (Update Routine) Allgemeine Java-Themen 6
L Launche update Allgemeine Java-Themen 19
D Update von TimerTask Allgemeine Java-Themen 13
J Eigenes Produkt Upgrade / Update-fähig halten? Allgemeine Java-Themen 16
S iText PDF - Verständnisproblem beim Update von TableCells (Seitenzahlen) Allgemeine Java-Themen 2
D Updaten von Klassen durch jar.exe zerstört diese. Update durch WinRAR gelingt! Allgemeine Java-Themen 2
T Update eines Programms - Beenden eines anderen Prozesses überwachen Allgemeine Java-Themen 8
D Java Update automatisieren Allgemeine Java-Themen 4
H SQL Update "Rückgabe der DB als String?" Allgemeine Java-Themen 7
X HTTP Problem mit static/non static JTextArea Update Allgemeine Java-Themen 17
S eigene Update Funktion Allgemeine Java-Themen 5
martin82 Java Runtime Update >17 - SwingWorker Änderungen? Allgemeine Java-Themen 7
M jdesktop binding: jTable update nach Änderung... Allgemeine Java-Themen 3
B Regex-Fehler nach lib-Update Allgemeine Java-Themen 2
H Probleme! Mac Os und Java Update Allgemeine Java-Themen 3
R JAR-Update in laufender Applikation Allgemeine Java-Themen 9
A Hilfe mit 2-dimensionalem array ***UPDATE*** Allgemeine Java-Themen 27
Kr0e JCE doFinal/update Allgemeine Java-Themen 2
MQue update/paint Allgemeine Java-Themen 7
L Java6 update N bekommt neues Browser-Plugin, bitte testen. Allgemeine Java-Themen 7
O App Update Allgemeine Java-Themen 3
T NullPointerException nach Java Update Allgemeine Java-Themen 4
V Update des JAR-Archivs Allgemeine Java-Themen 5
M Update auf netbeans 6Beta 1 Allgemeine Java-Themen 2
U Programm soll sich nach update neustarten Allgemeine Java-Themen 30
M Tool zum autom. Client-Update Allgemeine Java-Themen 2
C Java SE Runtime 6 Update 1 - IE 7 und FF 2.0 - Allgemeine Java-Themen 6
M Frage zu update Methode von Observer! Allgemeine Java-Themen 40
K Regex Versucher 2 *Update - sinnvoll und schön* :) Allgemeine Java-Themen 6
T update() wird bei Programmstart und resize nicht gemacht Allgemeine Java-Themen 4
R Browser-Problem nach Java-Update Allgemeine Java-Themen 9
B statusbar update -> mit thread oder listener? Allgemeine Java-Themen 7
D wie update-erinnerung der jre deaktivieren? Allgemeine Java-Themen 6
D repaint oder update Methode? Allgemeine Java-Themen 6
O Text aus einer Textdatei rausholen, der zwischen zwei Schlüsselworten steht Allgemeine Java-Themen 4
V Umgang mit fehlenden Daten in einer Java-Datenanalyseanwendung Allgemeine Java-Themen 5
M Methodenübersicht einer Klasse einsehen Allgemeine Java-Themen 14
T JNA, Aufruf der Funktionen einer dll Allgemeine Java-Themen 5
I Vom Monolith zu Services in einer Webseite Allgemeine Java-Themen 1
W Variable Initialisierung mit dem Ergebnis einer Regex Allgemeine Java-Themen 1
O Werte einer Generic LinkedList zusammenrechenen Allgemeine Java-Themen 14
C Sortieren und Selektieren einer ArrayList<Point3D> Allgemeine Java-Themen 6
A Einzelne Objekte und Unterobjekte einer ArrayList ausgeben Allgemeine Java-Themen 53
TheSepp Wie kann man Leerzeichen aus einer Array liste entfernen? Allgemeine Java-Themen 10
B Ein Objekt einer Klasse mehreren anderen Klassen zur Verfügung stellen? Allgemeine Java-Themen 6
M Optimierung einer Methode (byte-Geraffel) Allgemeine Java-Themen 2
I Wie kann ich den Wert aus einer If abfrage ausgeben Allgemeine Java-Themen 23
S HTML einer Webseite 1:1 so bekommen wie es auch der Browser anzeigt? Allgemeine Java-Themen 14
melaniemueller Einzelne Zeile aus einer txt Datei in einem String speichern Allgemeine Java-Themen 12
L Java überprüfen lassen, ob sich ein gegebener Pfad / das Programm an sich auf einer CD oder Festplatte befindet Allgemeine Java-Themen 14
J (Geplante) Änderungen an einer Datei vorübergehend speichern und anwenden? Allgemeine Java-Themen 12
ME2002 Fragen aus einer Java Klausur Allgemeine Java-Themen 67
_user_q Obfuscate einer .jar-Datei mit ProGuard? Allgemeine Java-Themen 2
_user_q Verknüpfung einer .jar-Datei (liegt z. B. auf dem Desktop) im Autostart-Ordner erstellen? Allgemeine Java-Themen 20
C Parsen einer sich updatenden Html mithilfe von jsoup Allgemeine Java-Themen 4
E Eine Methode einer extendeten Klasse deakitivieren Allgemeine Java-Themen 12
H Performance einer Monte-Carlo-Simulation verbessern Allgemeine Java-Themen 6
LimDul Kam eine java.net.URL zu einer HashMap und ging als DNS Anfrage wieder heraus Allgemeine Java-Themen 18
E Variablen Nach Übergabe einer Variable den Constructor aufrufen Allgemeine Java-Themen 16
Zeppi NullPointerException in einer if-Abfrage Allgemeine Java-Themen 6
D Abbruch einer ViewScoped Bean in Arbeit Allgemeine Java-Themen 2
Lukas2904 Schleife mit ansteuerung einer Klasse Allgemeine Java-Themen 5
d.lumpi Aus Einer Klasse auf ein Objekt einer anderen Klasse Zugreifen Allgemeine Java-Themen 1
Lukas2904 Wie kann man cps (ClicksPerSecond) in einer GUI anzeigen lassen? Allgemeine Java-Themen 4
O Produziert das Tool "jpackage" (ab JDK 14) .exe Dateien, die auf einer Zielumgebung ohne JRE lauffähig sind ?` Allgemeine Java-Themen 7
R Lambda Expression in einer Methode execute() aufrufen (execute() ist eine Methode aus dem funktionalen Interface Command) Allgemeine Java-Themen 5
Drachenbauer wie kann ich alle instanzen einer Klasse durchsehen, ohne, dass diese in einer Liste erzeugt wurden? Allgemeine Java-Themen 11
N BlueJ Implementation einer Analoguhr Allgemeine Java-Themen 0
O Formatierte String ausgabe bei vier Variablen in einer Zeile Allgemeine Java-Themen 1
N Speicherort einer Datei im Explorer ändern Allgemeine Java-Themen 8
O Datentypen Wie kann ich den Typ einer ArrayList abfragen ? Allgemeine Java-Themen 7
O Leerzeichen und Umlaute im Pfad einer Java Applikation machen Probleme Allgemeine Java-Themen 13
H Mehrere PNG-Files in einer Datei Allgemeine Java-Themen 9
G Java Editor Löschen doppelter Zahlen einer Liste Allgemeine Java-Themen 2
J JSON Daten von einer Webseite erhalten Allgemeine Java-Themen 2
L RegEx für Teile einer Berechnung Allgemeine Java-Themen 14
L Erste Schritte TDD testen einer Methode mit injezierten Services? Allgemeine Java-Themen 12
J Zerlegen einer Zahl Allgemeine Java-Themen 6
Zrebna Wie kann man endgültig aus einer Rekursion ausbrechen? Allgemeine Java-Themen 14
MiMa Person in einer Arraylist hinzugügen mit Prüfung ? Allgemeine Java-Themen 6
Meeresgott Effizientester Weg um nach der Value einer verschachtelten Map aufzulösen Allgemeine Java-Themen 5
H Mehrere Datentypen in einer Arraylist speichern Allgemeine Java-Themen 9
MiMa Prüfziffer einer EAN Nummer berechnen Allgemeine Java-Themen 4
MiMa Erstellungsdatum einer Datei Allgemeine Java-Themen 10
Drachenbauer Wie kann ich einer existierenden Enum von außerhalb veränderte Werte zuweisen? Allgemeine Java-Themen 5
S HTML den ich von einer URL hole nicht identisch mit dem HTML im Browser Allgemeine Java-Themen 1
S Rückgabe einer HttpURLConnection für eine Seite einlesen bei der man eingeloggt ist..? Allgemeine Java-Themen 5
O Java-Applikation tut in Netbeans, als JAR nicht, wegen Pfadangaben einer benötigten Datei Allgemeine Java-Themen 8
M Hilfe bei einer Java Programmieraufgabe! Ab morgen Montag um 08:00 Uhr Allgemeine Java-Themen 5

Ähnliche Java Themen

Neue Themen


Oben