Consejo 127 de Java: ver ejecución JAR

Puede empaquetar fácilmente todo el conjunto de clases y recursos de una aplicación en un archivo Java (JAR). De hecho, ese es uno de los objetivos de tener archivos jar. Otra es permitir que los usuarios ejecuten fácilmente la aplicación almacenada en el archivo. Entonces, ¿por qué los archivos jar son ciudadanos de segunda clase en el universo de Java (que funcionan solo como archivos) cuando pueden ser de primera clase, junto con los ejecutables nativos?

Para ejecutar un archivo jar, puede usar el

java

comando

-jar

opción. Por ejemplo, supongamos que tiene un archivo jar ejecutable llamado

myjar.jar

. Debido a que el archivo se puede ejecutar, puede ejecutarlo así:

java -jar myjar.jar

.

Alternativamente, Java Runtime Environment (JRE), cuando se instala en un sistema operativo como Microsoft Windows, asocia archivos jar con la JVM para que pueda hacer doble clic en ellos para ejecutar la aplicación. Estos JAR deben poder ejecutarse.

La pregunta es: ¿Cómo se puede ejecutar un JAR?

El archivo de manifiesto y la entrada Main-Class

Dentro de la mayoría de los archivos JAR, un archivo llamado

MANIFEST.MF

se almacena en un directorio llamado

META-INF

. Dentro de ese archivo, una entrada especial llamada

Main-Class

le dice al

java -jar

comando qué clase ejecutar.

El problema es que usted mismo debe agregar correctamente esta entrada especial al archivo de manifiesto; debe ir en un lugar determinado y debe tener un formato determinado. Sin embargo, a algunos de nosotros no nos gusta editar archivos de configuración.

Deje que la API lo haga por usted

Desde Java 1.2, un paquete llamado java.util.jarle permite trabajar con archivos jar. (Nota: se basa en el java.util.zippaquete). Específicamente, el paquete jar le permite manipular fácilmente ese archivo de manifiesto especial a través de la Manifestclase.

Escribamos un programa que use esta API. Primero, este programa debe conocer tres cosas:

  1. El JAR que deseamos hacer ejecutable
  2. La clase principal que deseamos ejecutar (esta clase debe existir dentro del JAR)
  3. El nombre de un nuevo JAR para nuestra salida, porque no deberíamos simplemente sobrescribir archivos

Escribe el programa

La lista anterior constituirá los argumentos de nuestro programa. En este punto, elija un nombre adecuado para esta aplicación. ¿Cómo MakeJarRunnablesuena?

Verifique los argumentos a main

Supongamos que nuestro principal punto de entrada es un main(String[])método estándar . Primero deberíamos comprobar los argumentos del programa aquí:

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

Preste atención a cómo se interpreta la lista de argumentos, ya que es importante para el siguiente código. El orden y el contenido de los argumentos no están escritos en piedra; sin embargo, recuerde modificar el otro código adecuadamente si lo cambia.

Acceda al JAR y su archivo de manifiesto

Primero, debemos crear algunos objetos que sepan sobre JAR y archivos de manifiesto:

// Cree el objeto JarInputStream y obtenga su manifiesto JarInputStream jarIn = new JarInputStream (new FileInputStream (args [0])); Manifiesto manifiesto = jarIn.getManifest (); if (manifest == null) {// Esto sucederá si no existe ningún manifiesto manifest = new Manifest (); }

Establecer el atributo Main-Class

Ponemos la Main-Classentrada en la sección de atributos principales del archivo de manifiesto. Una vez que obtenemos este conjunto de atributos del objeto manifiesto, podemos establecer la clase principal apropiada. Sin embargo, ¿qué pasa si un Main-Classatributo ya existe en el JAR original? Este programa simplemente imprime una advertencia y sale. Quizás podríamos agregar un argumento de línea de comando que le diga al programa que use el nuevo valor en lugar del preexistente:

Atributos a = manifest.getMainAttributes (); String oldMainClass = a.putValue ("Main-Class", args [1]); // Si existe un valor antiguo, dígale al usuario y salga if (oldMainClass! = Null) {System.out.println ("Advertencia: el valor antiguo de Main-Class es:" + oldMainClass); System.exit (1); }

Salida del nuevo JAR

Necesitamos crear un nuevo archivo jar, por lo que debemos usar la JarOutputStreamclase. Nota: Debemos asegurarnos de no usar el mismo archivo para la salida que para la entrada. Alternativamente, tal vez el programa debería considerar el caso donde los dos archivos jar son iguales y preguntar al usuario si desea sobrescribir el original. Sin embargo, me reservo esto como ejercicio para el lector. ¡Sigamos con el código!

 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 es actualmente un estudiante de posgrado en el departamento de ingeniería eléctrica e informática de la Universidad de Manitoba en Canadá. Comenzó a trabajar con Java a mediados de 1996 y lo ha estado usando casi exclusivamente desde entonces. Sus intereses actuales incluyen la simulación de campos eléctricos y fluidos, códigos de corrección de errores y la implementación de ingeniosos trucos GUI (interfaz gráfica de usuario). Shawn también imparte un curso de diseño de software de tercer año en el departamento de ingeniería informática de su universidad.

Más información sobre este tema

  • Descargue el código fuente y los archivos JAR para este consejo

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

  • "Java Tip 120Execute Self-Extracting JARs", Z. Steve Jin y John D. Mitchell ( JavaWorld, noviembre de 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

  • Manténgase al tanto de nuestros trucos y sugerencias suscribiéndose a los boletines informativos semanales gratuitos por correo electrónico de JavaWorld

    //www.javaworld.com/subscribe

  • Aprender los conceptos básicos de Java del lado del cliente en JavaWorld' s Java Principiante discusión. Los temas centrales incluyen el lenguaje Java, la máquina virtual Java, API y herramientas de desarrollo.

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

  • Encontrará una gran cantidad de artículos relacionados con TI de nuestras publicaciones hermanas en .net

Esta historia, "Java Tip 127: Ver ejecución de JAR" fue publicada originalmente por JavaWorld.