2010-01-07 8 views
4

Je voudrais écrire une application Java qui peut créer des fichiers jar exécutables lors de l'exécution. Le "hello world" de ce que je veux faire est d'écrire une application Java X qui, lorsqu'elle est exécutée, génère un fichier exécutable Y qui, lorsqu'il est exécuté, affiche hello world (ou peut-être une autre chaîne inconnue qu'après l'exécution de Y).générer un fichier exécutable jar à l'exécution

Comment puis-je accomplir ceci?

Répondre

5

Les autres réponses nécessitent le démarrage d'un nouveau processus, il s'agit d'une méthode qui ne l'est pas. Voici trois définitions de classe qui produisent le scénario de bonjour décrit dans la question.

Lorsque vous exécutez XMain.main, il génère /tmp/y.jar. Ensuite, lorsque vous exécutez cela à la ligne de commande:

java -jar /tmp/y.jar cool 

Il imprime:

Hello darling Y! 
cool 

exemple/YMain.java

package example; 

import java.io.IOException; 
import java.io.InputStream; 

public class YMain { 

    public static void main(String[] args) throws IOException { 
     // Fetch and print message from X 
     InputStream fromx = YMain.class.getClassLoader().getResourceAsStream("fromx.txt"); 
     System.out.println(new String(Util.toByteArray(fromx))); 

     // Print first command line argument 
     System.out.println(args[0]); 
    } 
} 

exemple/XMain.java

package example; 

import java.io.FileOutputStream; 
import java.io.IOException; 
import java.util.jar.Attributes; 
import java.util.jar.JarEntry; 
import java.util.jar.JarOutputStream; 
import java.util.jar.Manifest; 

public class XMain { 

    public static void main(String[] args) throws IOException { 
     Manifest manifest = new Manifest(); 
     manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0"); 
     manifest.getMainAttributes().put(Attributes.Name.MAIN_CLASS, YMain.class.getName()); 
     JarOutputStream jarOutputStream = new JarOutputStream(new FileOutputStream("/tmp/y.jar"), manifest); 

     // Add the main class 
     addClass(YMain.class, jarOutputStream); 

     // Add the Util class; Y uses it to read our secret message 
     addClass(Util.class, jarOutputStream); 

     // Add a secret message 
     jarOutputStream.putNextEntry(new JarEntry("fromx.txt")); 
     jarOutputStream.write("Hello darling Y!".getBytes()); 
     jarOutputStream.closeEntry(); 

     jarOutputStream.close(); 
    } 

    private static void addClass(Class c, JarOutputStream jarOutputStream) throws IOException 
    { 
     String path = c.getName().replace('.', '/') + ".class"; 
     jarOutputStream.putNextEntry(new JarEntry(path)); 
     jarOutputStream.write(Util.toByteArray(c.getClassLoader().getResourceAsStream(path))); 
     jarOutputStream.closeEntry(); 
    } 
} 

exemple/Util.java

package example; 

import java.io.ByteArrayOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 

public class Util { 

    public static byte[] toByteArray(InputStream in) throws IOException { 
     ByteArrayOutputStream out = new ByteArrayOutputStream(); 
     byte[] buf = new byte[0x1000]; 
     while (true) { 
      int r = in.read(buf); 
      if (r == -1) { 
       break; 
      } 
      out.write(buf, 0, r); 
     } 
     return out.toByteArray(); 
    } 
} 
2

Avez-vous besoin de l'écrire en Java ancien? J'utiliserais Gradle (un outil de construction basé sur Groovy). Vous pouvez avoir une tâche personnalisée pour écrire les fichiers source pour Y (Groovy rend vraiment facile d'écrire des fichiers modèles). Gradle facilite la génération d'un fichier exécutable.

Si vous voulez vraiment créer vos propres fichiers, vous devez utiliser ZipOutStream pour compresser les fichiers compilés après avoir appelé javac via l'API Process pour compiler la source.

Peut-être un peu plus d'informations sur la raison pour laquelle vous voulez faire cela aider à obtenir de meilleures réponses

acclamations

Lee

0

Étape 1: comprendre comment le faire manuellement à l'aide de la ligne de commande. Étape 2: automatisez ceci en appelant le programme depuis Java.

http://devdaily.com/java/edu/pj/pj010016/

Pour l'étape 1 Je suggère d'utiliser des fourmis - IDEs ne sont pas toujours automatisable. Donc, soit écrire tous les fichiers de Java, ou avoir certaines configurations de fourmis incluses comme ressources dans le projet.

+0

Mais vous pouvez faire mieux que cela. Les étapes de compilation Java et de création de fichier JAR peuvent toutes deux être effectuées dans la JVM en cours. –

+0

C'est ce que j'avais espéré. Je ne veux pas générer un nouveau processus ou dépendre de l'environnement de la machine hôte, autre que l'installation de JRE.Avez-vous un lien vers un exemple, Stephen? –

1

Pour développer la réponse de Lee, vous devez d'abord compiler la source. Vous pouvez utiliser le processus ou vous pouvez utiliser le code de tools.jar directement comme explained here. Ensuite, écrivez un fichier MANIFEST.MF et mettez tout ensemble en utilisant ZipOutputStream comme mentionné.

Questions connexes