106 votes

Comment puis-je écrire une application Java qui peut se mettre à jour au moment de l'exécution ?

J'aimerais mettre en place une application Java (application serveur) qui peut télécharger une nouvelle version (fichier .jar) à partir d'une url donnée, puis se mettre à jour au moment de l'exécution.

Quelle est la meilleure façon de procéder et est-ce possible ?

Je suppose que l'application peut télécharger un nouveau fichier .jar et le lancer. Mais comment dois-je procéder au transfert, c'est-à-dire savoir quand la nouvelle application est lancée et quitter. Ou existe-t-il une meilleure façon de procéder ?

4 votes

Avez-vous examiné Java Web Start ? Il ne se met pas à jour au moment de l'exécution, je crois, (redémarrage nécessaire), pour cela vous devez probablement vous tourner vers OSGi.

0 votes

@Thilo : Je pense qu'il serait facile de télécharger un fichier à partir d'une url donnée, puis de le démarrer avec une commande linux à partir du fichier jar en cours d'exécution.

2 votes

La conception de l'API Java WebStart rend impossible la mise à jour en cours d'exécution. Malheureusement, il n'est pas possible de mettre à jour l'API Java WebStart en cours de fonctionnement.

75voto

Stephen C Points 255558

La structure de base d'une solution est la suivante :

  • Une boucle principale est responsable du chargement répété de la dernière version de l'application (si nécessaire) et de son lancement.

  • L'application fait son travail, mais vérifie périodiquement l'URL de téléchargement. Si elle détecte une nouvelle version, elle retourne au lanceur.

Il y a plusieurs façons de mettre cela en œuvre. Par exemple :

  • Le lanceur peut être un wrapper script ou une application binaire qui démarre une nouvelle JVM pour exécuter l'application à partir d'un fichier JAR qui est remplacé.

  • Le lanceur pourrait être une application Java qui crée un classloader pour le nouveau JAR, charge une classe d'entrée et appelle une méthode sur celle-ci. Si vous procédez de cette manière, vous devez surveiller les fuites de stockage du classloader, mais ce n'est pas difficile. (Vous devez simplement vous assurer qu'aucun objet contenant des classes chargées à partir du JAR n'est accessible après le redémarrage).

Les avantages de l'approche de l'enveloppe externe sont les suivants :

  • vous n'avez besoin que d'un seul JAR,
  • vous pouvez remplacer toute l'application Java,
  • tous les threads secondaires créés par l'application, etc. disparaîtront sans logique d'arrêt particulière, et
  • vous pouvez également vous occuper de la récupération après des pannes d'application, etc.

La deuxième approche nécessite deux JAR, mais présente les avantages suivants :

  • la solution est purement Java et portable,
  • le changement sera plus rapide, et
  • vous pouvez plus facilement conserver l'état à travers le redémarrage (modulo les problèmes de fuite).

La "meilleure" méthode dépend de vos besoins spécifiques.

Il convient également de noter que :

  • La mise à jour automatique présente des risques pour la sécurité. En général, si le serveur qui fournit les mises à jour est compromis, ou si les mécanismes de fourniture des mises à jour sont susceptibles d'être attaqués, alors la mise à jour automatique peut conduire à une compromission du ou des clients.

  • L'envoi à un client d'une mise à jour qui lui porte préjudice peut entraîner des risques juridiques et des risques pour la réputation de votre entreprise.


Si vous pouvez trouver un moyen d'éviter de réinventer la roue, ce serait bien. Voir les autres réponses pour des suggestions.

47voto

Berdus Points 76

Je développe actuellement un Daemon JAVA Linux et j'ai eu besoin de mettre en place un mécanisme de mise à jour automatique. Je voulais limiter mon application à un seul fichier jar et j'ai trouvé une solution simple :

Intégrer l'application de mise à jour dans la mise à jour elle-même.

Application : Lorsque l'application détecte une version plus récente, elle effectue les opérations suivantes :

  1. Télécharger la mise à jour (Zipfile)
  2. Application de l'extrait et ApplicationUpdater (tous dans le fichier zip)
  3. Lancer le programme de mise à jour

ApplicationUpdater : Lorsque le programme de mise à jour s'exécute, il effectue les opérations suivantes :

  1. Arrêter l'application (dans mon cas un démon via init.d)
  2. Copier le fichier jar téléchargé pour remplacer l'application actuelle
  3. Démarrer l'application
  4. Nettoyage.

J'espère que cela aidera quelqu'un.

14voto

Peter Knego Points 57985

Il s'agit d'un problème connu et je recommande de ne pas réinventer la roue - n'écrivez pas votre propre hack, utilisez simplement ce que d'autres ont déjà fait.

Deux situations à prendre en compte :

  1. L'application doit être auto-adaptable et continuer à fonctionner même pendant la mise à jour (application serveur, applications intégrées). Optez pour OSGi : Liasses o Equinoxe p2 .

  2. L'application est une application de bureau et dispose d'un programme d'installation. Il existe de nombreux programmes d'installation avec option de mise à jour. Vérifier liste des installateurs .

11voto

Brad Mace Points 12173

J'ai écrit une application Java qui peut charger des plugins au moment de l'exécution et commencer à les utiliser immédiatement, en s'inspirant d'un mécanisme similaire dans jEdit. jEdit est un logiciel libre, vous avez donc la possibilité de voir comment il fonctionne.

La solution utilise un ClassLoader personnalisé pour charger les fichiers à partir du jar. Une fois qu'ils sont chargés, vous pouvez invoquer une méthode du nouveau jar qui agira comme son main méthode. Ensuite, la partie la plus délicate est de s'assurer que vous vous débarrassez de toutes les références à l'ancien code afin qu'il puisse être ramassé par les éboueurs. Je ne suis pas vraiment un expert en la matière, mais j'ai réussi à le faire, mais ce n'était pas facile.

0 votes

Je ne sais pas ce qu'il en est pour Java, mais en C#, vous pouvez utiliser les AppDomains pour décharger explicitement le code. Il existe peut-être un concept similaire en Java.

1 votes

Merci, cela semble être la voie à suivre. Il y a un exemple de NetworkClassLoader sur la JavaDoc pour ClassLoader

0 votes

Avez-vous rencontré des problèmes avec les variables statiques au sein de la même JVM, ou avec la génération permanente ? J'ai entendu dire qu'elles pouvaient poser des problèmes en ce qui concerne le déchargement des classes.

7voto

ycnix Points 309
  1. Première solution : utiliser tomcat et ses fonctions de déploiement.
  2. Deuxième méthode : diviser l'application en deux parties (fonctionnelle et mise à jour) et laisser la partie mise à jour remplacer la partie fonctionnelle.
  3. Troisième voie : Dans votre application serveur, téléchargez la nouvelle version, puis l'ancienne version libère le port lié, l'ancienne version exécute la nouvelle version (démarre le processus), puis l'ancienne version envoie une demande sur le port de l'application à la nouvelle version pour supprimer l'ancienne version, l'ancienne version se termine et la nouvelle version supprime l'ancienne version. Voici ce qui se passe : alt text

0 votes

Votre deuxième solution semble être une conception intéressante.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X