Suggerimento Java 127: vedere Esecuzione di JAR

È possibile creare facilmente un pacchetto dell'intero set di classi e risorse di un'applicazione in un JAR (Java Archive). In effetti, questo è uno degli obiettivi di avere file jar. Un altro è quello di consentire agli utenti di eseguire facilmente l'applicazione memorizzata nell'archivio. Perché allora i file jar sono cittadini di seconda classe nell'universo Java - funzionano solo come archivi - quando possono essere di prima classe, proprio accanto agli eseguibili nativi?

Per eseguire un file jar, puoi usare il

java

comando di

-jar

opzione. Ad esempio, supponiamo di avere un file jar eseguibile chiamato

myjar.jar

. Poiché il file è eseguibile, puoi eseguirlo in questo modo:

java -jar myjar.jar

.

In alternativa, Java Runtime Environment (JRE), se installato su un sistema operativo come Microsoft Windows, associa i file jar con la JVM in modo da poter fare doppio clic su di essi per eseguire l'applicazione. Questi JAR devono essere eseguibili.

La domanda è: come si rende eseguibile un JAR?

Il file manifest e la voce Main-Class

Nella maggior parte dei JAR, un file chiamato

MANIFEST.MF

è memorizzato in una directory chiamata

META-INF

. All'interno di quel file, una voce speciale chiamata

Main-Class

dice al

java -jar

comando quale classe eseguire.

Il problema è che devi aggiungere correttamente questa voce speciale al file manifest: deve essere inserita in un determinato punto e deve avere un determinato formato. Tuttavia, ad alcuni di noi non piace modificare i file di configurazione.

Lascia che l'API lo faccia per te

A partire da Java 1.2, un pacchetto chiamato ti java.util.jarha permesso di lavorare con i file jar. (Nota: si basa sul java.util.zippacchetto.) In particolare, il pacchetto jar consente di manipolare facilmente quel file manifest speciale tramite la Manifestclasse.

Scriviamo un programma che utilizzi questa API. Innanzitutto, questo programma deve conoscere tre cose:

  1. Il JAR che desideriamo rendere eseguibile
  2. La classe principale che desideriamo eseguire (questa classe deve esistere all'interno del JAR)
  3. Il nome di un nuovo JAR per il nostro output, perché non dovremmo semplicemente sovrascrivere i file

Scrivi il programma

L'elenco di cui sopra costituirà gli argomenti del nostro programma. A questo punto, scegliamo un nome adatto per questa applicazione. Come MakeJarRunnablesuona?

Controlla gli argomenti di main

Supponiamo che il nostro punto di ingresso principale sia un main(String[])metodo standard . Dovremmo prima controllare gli argomenti del programma qui:

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

Prestare attenzione a come viene interpretato l'elenco degli argomenti, poiché è importante per il codice seguente. L'ordine e il contenuto degli argomenti non sono definiti nella pietra; tuttavia, ricordarsi di modificare l'altro codice in modo appropriato se lo si cambia.

Accedi al JAR e al suo file manifest

Innanzitutto, dobbiamo creare alcuni oggetti che conoscano i file JAR e manifest:

// Crea l'oggetto JarInputStream e ottieni il suo manifesto JarInputStream jarIn = new JarInputStream (new FileInputStream (args [0])); Manifest manifest = jarIn.getManifest (); if (manifest == null) {// Questo accadrà se non esiste alcun manifest manifest = new Manifest (); }

Imposta l'attributo Main-Class

Inseriamo la Main-Classvoce nella sezione degli attributi principali del file manifest. Una volta ottenuto questo set di attributi dall'oggetto manifest, possiamo impostare la classe principale appropriata. Tuttavia, cosa succede se un Main-Classattributo esiste già nel JAR originale? Questo programma stampa semplicemente un avviso ed esce. Forse potremmo aggiungere un argomento della riga di comando che dice al programma di utilizzare il nuovo valore invece di quello preesistente:

Attributi a = manifest.getMainAttributes (); String oldMainClass = a.putValue ("Main-Class", args [1]); // Se esiste un vecchio valore, informa l'utente ed esci se (oldMainClass! = Null) {System.out.println ("Avvertenza: il vecchio valore Main-Class è:" + oldMainClass); System.exit (1); }

Produci il nuovo JAR

Dobbiamo creare un nuovo file jar, quindi dobbiamo usare la JarOutputStreamclasse. Nota: dobbiamo assicurarci di non utilizzare lo stesso file per l'output come per l'input. In alternativa, forse il programma dovrebbe considerare il caso in cui i due file jar sono gli stessi e chiedere all'utente se desidera sovrascrivere l'originale. Tuttavia, lo riservo come esercizio per il lettore. Avanti con il codice!

 System.out.println("Writing to " + args[2] + "..."); JarOutputStream jarOut = new JarOutputStream(new FileOutputStream(args[2]), manifest); 

We must write every entry from the input JAR to the output JAR, so iterate over the entries:

 //Create a read buffer to transfer data from the input byte[] buf = new byte[4096]; //Iterate the entries JarEntry entry; while ((entry = jarIn.getNextJarEntry()) != null) { //Exclude the manifest file from the old JAR if ("META-INF/MANIFEST.MF".equals(entry.getName())) continue; //Write the entry to the output JAR jarOut.putNextEntry(entry); int read; while ((read = jarIn.read(buf)) != -1) { jarOut.write(buf, 0, read); } jarOut.closeEntry(); } //Flush and close all the streams jarOut.flush(); jarOut.close(); jarIn.close(); 

Complete program

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 è attualmente uno studente laureato nel dipartimento di ingegneria elettrica e informatica dell'Università di Manitoba in Canada. Ha iniziato a lavorare con Java a metà del 1996 e da allora lo utilizza quasi esclusivamente. I suoi attuali interessi includono la simulazione di campi elettrici e fluidi, codici di correzione degli errori e l'implementazione di ingegnosi trucchi GUI (interfaccia utente grafica). Shawn insegna anche un corso di progettazione del software del terzo anno nel dipartimento di ingegneria informatica della sua università.

Ulteriori informazioni su questo argomento

  • Scarica il codice sorgente e i JAR per questo suggerimento

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

  • "Java Tip 120Execute Self-Extracting JARs", Z. Steve Jin e 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

  • Rimani aggiornato sui nostri Tips 'N Tricks iscrivendoti alle newsletter settimanali gratuite via email di JavaWorld

    //www.javaworld.com/subscribe

  • Nozioni di base di Java lato client in JavaWorld' s Java principianti discussione. Gli argomenti principali includono il linguaggio Java, la Java Virtual Machine, le API e gli strumenti di sviluppo

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

  • Troverai una vasta gamma di articoli relativi all'IT tratti dalle nostre pubblicazioni gemelle su .net

Questa storia, "Java Tip 127: See JAR run" è stata originariamente pubblicata da JavaWorld.