Astuce Java 127: voir l'exécution du JAR

Vous pouvez facilement regrouper l'ensemble des classes et des ressources d'une application dans une archive Java (JAR). En fait, c'est l'un des objectifs d'avoir des fichiers jar. Une autre consiste à permettre aux utilisateurs d'exécuter facilement l'application stockée dans l'archive. Pourquoi alors les fichiers jar sont-ils des citoyens de seconde zone dans l'univers Java - ne fonctionnent que comme des archives - alors qu'ils peuvent être de première classe, juste à côté des exécutables natifs?

Pour exécuter un fichier jar, vous pouvez utiliser le

java

commande

-jar

option. Par exemple, supposons que vous ayez un fichier jar exécutable appelé

myjar.jar

. Puisque le fichier est exécutable, vous pouvez l'exécuter comme ceci:

java -jar myjar.jar

.

Alternativement, l'environnement d'exécution Java (JRE), lorsqu'il est installé sur un système d'exploitation tel que Microsoft Windows, associe les fichiers jar à la JVM afin que vous puissiez double-cliquer dessus pour exécuter l'application. Ces fichiers JAR doivent être exécutables.

La question est: comment rendre un JAR exécutable?

Le fichier manifeste et l'entrée Main-Class

Dans la plupart des JAR, un fichier appelé

MANIFEST.MF

est stocké dans un répertoire appelé

META-INF

. Dans ce fichier, une entrée spéciale appelée

Main-Class

raconte le

java -jar

commande quelle classe exécuter.

Le problème est que vous devez correctement ajouter vous-même cette entrée spéciale au fichier manifeste - elle doit aller à un certain endroit et avoir un certain format. Cependant, certains d'entre nous n'aiment pas éditer les fichiers de configuration.

Laissez l'API le faire pour vous

Depuis Java 1.2, un package appelé java.util.jarvous permet de travailler avec des fichiers jar. (Remarque: il s'appuie sur le java.util.zippackage.) Plus précisément, le package jar vous permet de manipuler facilement ce fichier manifeste spécial via la Manifestclasse.

Écrivons un programme qui utilise cette API. Tout d'abord, ce programme doit connaître trois choses:

  1. Le JAR que nous souhaitons rendre exécutable
  2. La classe principale que nous souhaitons exécuter (cette classe doit exister dans le JAR)
  3. Le nom d'un nouveau JAR pour notre sortie, car nous ne devrions pas simplement écraser les fichiers

Ecrire le programme

La liste ci-dessus constituera les arguments de notre programme. À ce stade, choisissons un nom approprié pour cette application. Comment ça MakeJarRunnablesonne?

Vérifiez les arguments de main

Supposons que notre point d'entrée principal soit une main(String[])méthode standard . Nous devons d'abord vérifier les arguments du programme ici:

if (args.length! = 3) {System.out.println ("Utilisation: MakeJarRunnable" + ""); System.exit (0); }

Veuillez faire attention à la façon dont la liste d'arguments est interprétée, car c'est important pour le code suivant. L'ordre et le contenu des arguments ne sont pas gravés dans la pierre; cependant, n'oubliez pas de modifier les autres codes de manière appropriée si vous les modifiez.

Accéder au JAR et à son fichier manifeste

Tout d'abord, nous devons créer des objets qui connaissent les fichiers JAR et manifestes:

// Créez l'objet JarInputStream et récupérez son manifeste JarInputStream jarIn = new JarInputStream (new FileInputStream (args [0])); Manifest manifest = jarIn.getManifest (); if (manifest == null) {// Cela se produira si aucun manifeste n'existe manifest = new Manifest (); }

Définir l'attribut Main-Class

Nous mettons l' Main-Classentrée dans la section des attributs principaux du fichier manifeste. Une fois que nous avons obtenu cet ensemble d'attributs à partir de l'objet manifeste, nous pouvons définir la classe principale appropriée. Cependant, que se passe-t-il si un Main-Classattribut existe déjà dans le JAR d'origine? Ce programme imprime simplement un avertissement et se ferme. Nous pourrions peut-être ajouter un argument de ligne de commande qui indique au programme d'utiliser la nouvelle valeur au lieu de la valeur préexistante:

Attributs a = manifest.getMainAttributes (); String oldMainClass = a.putValue ("Main-Class", args [1]); // Si une ancienne valeur existe, informez l'utilisateur et quittez if (oldMainClass! = Null) {System.out.println ("Attention: l'ancienne valeur de la classe principale est:" + oldMainClass); System.exit (1); }

Sortir le nouveau JAR

Nous devons créer un nouveau fichier jar, nous devons donc utiliser la JarOutputStreamclasse. Remarque: nous devons nous assurer de ne pas utiliser le même fichier pour la sortie que pour l'entrée. Sinon, le programme devrait peut-être envisager le cas où les deux fichiers jar sont identiques et demander à l'utilisateur s'il souhaite écraser l'original. Cependant, je réserve cet exercice au lecteur. Avec le code!

System.out.println ("Ecriture dans" + args [2] + "..."); JarOutputStream jarOut = nouveau JarOutputStream (nouveau FileOutputStream (args [2]), manifeste);

Nous devons écrire chaque entrée du JAR d'entrée vers le JAR de sortie, donc itérer sur les entrées:

// Crée un tampon de lecture pour transférer les données de l'octet d'entrée [] buf = new byte [4096]; // Itère les entrées JarEntry entry; while ((entry = jarIn.getNextJarEntry ())! = null) {// Exclut le fichier manifeste de l'ancien JAR if ("META-INF / MANIFEST.MF" .equals (entry.getName ())) continue; // Ecrit l'entrée dans le JAR de sortie jarOut.putNextEntry (entrée); int lu; while ((read = jarIn.read (buf))! = -1) {jarOut.write (buf, 0, read); } jarOut.closeEntry (); } // Vide et ferme tous les flux jarOut.flush (); jarOut.close (); jarIn.close ();

Programme complet

Of course, we must place this code inside a main method, inside a class, and with a suitable set of import statements. The Resources section provides the complete program.

Usage example

Let's put this program to use with an example. Suppose you have an application whose main entry point is in a class called HelloRunnableWorld. (This is the full class name.) Also assume that you've created a JAR called myjar.jar, containing the entire application. Run MakeJarRunnable on this jar file like so:

 java MakeJarRunnable myjar.jar HelloRunnableWorld myjar_r.jar 

Again, as mentioned earlier, notice how I order the argument list. If you forget the order, just run this program with no arguments and it will respond with a usage message.

Try to run the

java -jar

command on

myjar.jar

and then on

myjar_r.jar

. Note the difference! After you've done that, explore the manifest files (

META-INF/MANIFEST.MF

) in each JAR. (You can find both JARs in the

source code

.)

Here's a suggestion: Try to make the MakeJarRunnable program into a runnable JAR!

Run with it

Running a JAR by double-clicking it or using a simple command is always more convenient than having to include it in your classpath and running a specific main class. To help you do this, the JAR specification provides a Main-Class attribute for the JAR's manifest file. The program I present here lets you utilize Java's JAR API to easily manipulate this attribute and make your JARs runnable.

Shawn Silverman est actuellement étudiant diplômé au département de génie électrique et informatique de l'Université du Manitoba au Canada. Il a commencé à travailler avec Java au milieu de 1996 et l'utilise presque exclusivement depuis. Ses intérêts actuels incluent la simulation des champs électriques et des fluides, les codes de correction d'erreurs et la mise en œuvre de trucs astucieux GUI (interface utilisateur graphique). Shawn enseigne également un cours de conception de logiciels de troisième année au département de génie informatique de son université.

En savoir plus sur ce sujet

  • Téléchargez le code source et les fichiers JAR de cette astuce

    //images.techhive.com/downloads/idge/imported/article/jvw/2002/05/makejarrunnable.zip

  • «Java Tip 120Execute Self-Extracting JARs», Z. Steve Jin et John D. Mitchell ( JavaWorld, novembre 2001)

    //www.javaworld.com/javaworld/javatips/jw-javatip120.html

  • JAR File Specification

    //java.sun.com/j2se/1.3/docs/guide/jar/jar.html

  • jar—The Java Archive Tool

    //java.sun.com/j2se/1.3/docs/tooldocs/win32/jar.html

  • View all previous Java Tips and submit your own

    //www.javaworld.com/javatips/jw-javatips.index.html

  • Learn Java from the ground up in JavaWorld's Java 101 column

    //www.javaworld.com/javaworld/topicalindex/jw-ti-java101.html

  • Java experts answer your toughest Java questions in JavaWorld's Java Q&A column

    //www.javaworld.com/javaworld/javaqa/javaqa-index.html

  • Browse the Core Java section of JavaWorld's Topical Index

    //www.javaworld.com/channel_content/jw-core-index.shtml

  • Restez au courant de nos conseils et astuces en vous abonnant aux newsletters hebdomadaires gratuites de JavaWorld

    //www.javaworld.com/subscribe

  • Apprenez les bases de Java côté client dans « JavaWorld de Java Débutant discussion. Les sujets principaux incluent le langage Java, la machine virtuelle Java, les API et les outils de développement

    //forums.idg.net/[email protected]@.ee6b804

  • Vous trouverez une multitude d'articles liés à l'informatique provenant de nos publications sœurs sur .net

Cette histoire, "Java Tip 127: See JAR run" a été publiée à l'origine par JavaWorld.