web-dev-qa-db-fra.com

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

Je souhaite implémenter une application Java (application serveur) pouvant télécharger une nouvelle version (fichier .jar) à partir d'une URL donnée, puis se mettre à jour au moment de l'exécution.

Quel est le meilleur moyen de le faire et est-ce possible?

Je suppose que l'application peut télécharger un nouveau fichier .jar et le démarrer. Mais comment dois-je faire le transfert, par exemple savoir quand la nouvelle application est lancée puis quitter. Ou y a-t-il une meilleure façon de faire cela?

78
Jonas

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

  • Il existe une boucle principale chargée de charger de manière répétée la dernière version de l'application (si nécessaire) et de la lancer.

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

Vous pouvez mettre cela en œuvre de différentes manières. Par exemple:

  • Le programme de lancement peut être un script wrapper ou une application binaire qui démarre une nouvelle machine virtuelle Java pour exécuter l'application à partir d'un fichier JAR remplacé.

  • Le programme de lancement peut être une application Java qui crée un chargeur de classes pour le nouveau JAR, charge une classe de point d'entrée et appelle une méthode dessus. Si vous procédez ainsi, vous devez surveiller les fuites de stockage du chargeur de classe, mais ce n'est pas difficile. (Vous devez simplement vous assurer qu'aucun objet contenant des classes chargées à partir du fichier JAR n'est accessible après le redémarrage.)

Les avantages de l’approche externe sont les suivants:

  • vous n'avez besoin que d'un seul pot, 
  • vous pouvez remplacer l'ensemble de l'application Java,
  • tous les fils secondaires créés par l'application, etc. disparaîtront sans logique d'arrêt spéciale, et
  • vous pouvez également gérer la récupération après un blocage d'application, etc.

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

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

Le "meilleur" moyen dépend de vos besoins spécifiques.

Il convient également de noter que:

  • Il y a des risques de sécurité avec la mise à jour automatique. En général, si le serveur qui fournit les mises à jour est compromis ou si les mécanismes permettant de fournir les mises à jour sont susceptibles d'attaques, la mise à jour automatique peut alors compromettre le ou les clients.

  • Transmettre à un client une mise à jour causant un préjudice à celui-ci peut comporter des risques juridiques, ainsi que des atteintes à 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.

55
Stephen C

Je développe actuellement un démon Java Linux et je devais également mettre en place un mécanisme de mise à jour automatique. Je voulais limiter mon application à un fichier jar et j'ai proposé une solution simple: 

Pack 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. Extraire Application et ApplicationUpdater (tous dans le fichier zip)
  3. Exécuter le programme de mise à jour

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

  1. Arrêtez l'application (dans mon cas, un démon via init.d)
  2. Copiez le fichier JAR téléchargé pour écraser l'application actuelle.
  3. Lancer l'application
  4. Nettoyer.

J'espère que ça aide quelqu'un.

35
Berdus

J'ai écrit une application Java qui peut charger des plugins au moment de l'exécution et commencer à les utiliser immédiatement, inspirée par un mécanisme similaire dans jEdit. jEdit est open source, vous avez donc la possibilité de voir comment cela fonctionne.

La solution utilise un ClassLoader personnalisé pour charger des fichiers à partir du fichier jar. Une fois qu'ils sont chargés, vous pouvez appeler une méthode du nouveau fichier jar qui agira comme sa méthode main. Ensuite, la partie délicate consiste à vous débarrasser de toutes les références à l’ancien code afin qu’il puisse être nettoyé. Je ne suis pas tout à fait un expert sur ce point, j'ai fait en sorte que cela fonctionne, mais ce n'était pas facile.

10
Brad Mace

C'est un problème connu et je recommande de ne pas réinventer une roue - n'écrivez pas votre propre piratage, utilisez simplement ce que d'autres personnes ont déjà fait.

Deux situations à prendre en compte:

  1. L'application doit pouvoir être mise à jour automatiquement et continuer à fonctionner même pendant la mise à jour (application serveur, applications intégrées). Allez avec OSGi: Bundles ou Equinox p2 .

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

9
Peter Knego
  1. Première façon: utilisez Tomcat et ses installations de déploiement.
  2. Seconde façon: diviser l’application en deux parties (fonctionnelle et mise à jour) et laisser la partie mise à jour remplacer la partie fonction.
  3. Troisième manière: dans votre application de serveur, téléchargez simplement la nouvelle version, puis l'ancienne version publie le port lié, puis l'ancienne version exécute la nouvelle version (processus en cours), puis l'ancienne version envoie une demande sur le port de l'application à la nouvelle version pour supprimer l'ancienne version se termine et la nouvelle version supprime l'ancienne version. Comme ça:alt text
5
jnr

J'ai récemment créé update4j , qui est entièrement compatible avec le système de modules de Java 9.

La nouvelle version démarrera de manière transparente sans redémarrage.

4
Mordechai

Si vous créez votre application à l'aide des plug-ins Equinox , vous pouvez utiliser le système de provisionnement P2 pour obtenir une solution toute prête à ce problème. Cela nécessitera que le serveur se redémarre après une mise à jour.

2
Tom Crockett

Ce n'est pas forcément le chemin meilleur, mais cela pourrait fonctionner pour vous.

Vous pouvez écrire une application bootstrap (comme le lanceur World of Warcraft, si vous avez déjà joué à WoW). Ce bootstrap est responsable de la vérification des mises à jour.

  • Si une mise à jour est disponible, elle sera proposée à l'utilisateur, gérera le téléchargement, l'installation, etc.
  • Si l'application est à jour, elle permettra à l'utilisateur de lancer l'application.
  • Facultativement, vous pouvez autoriser l'utilisateur à lancer l'application, même si celle-ci n'est pas à jour.

De cette façon, vous n'avez pas à vous soucier de forcer la sortie de votre application.

Si votre application est basée sur le Web et s'il est important qu'elle dispose d'un client à jour, vous pouvez également effectuer des vérifications de version pendant l'exécution de l'application. Vous pouvez les effectuer à intervalles réguliers, tout en établissant une communication normale avec le serveur (tout ou partie des appels), ou les deux.

Pour un produit sur lequel j'ai récemment travaillé, nous avons effectué des vérifications de version au lancement (sans application de démarrage, mais avant l'apparition de la fenêtre principale), ainsi que lors d'appels au serveur. Lorsque le client était obsolète, nous nous sommes appuyés sur l'utilisateur pour quitter manuellement, mais interdisons toute action contre le serveur.

Veuillez noter que je ne sais pas si Java peut appeler le code de l'interface utilisateur avant d'afficher votre fenêtre principale. Nous utilisions C #/WPF.

2

Je vois un problème de sécurité lors du téléchargement d’un nouveau bocal (etc.), par exemple un homme au milieu d’une attaque. Vous devez toujours signer votre mise à jour téléchargeable.

Sur JAX2015, Adam Bien a expliqué comment utiliser JGit pour mettre à jour les fichiers binaires . Malheureusement, je n’ai trouvé aucun tutoriel.

Source en allemand.

Adam Bien a créé le programme de mise à jour voir ici

Je l'ai bifurqué ici avec une interface javaFX. Je travaille également sur une signature automatique.

0
Kaito