Generate an executable jar at runtime

I would like to write a Java application that can create executable jars at runtime. “Hello world” of what I want to do is write a Java X application that, at startup, generates an executable jar Y, which at startup prints the world hello (or perhaps another line, unknown until Y is launched) .

How can i do this?

+4
source share
4 answers

Other answers require starting a new process; this is a method that does not. Here are 3 class definitions that create the welcome script described in the question.

When you start XMain.main, it generates /tmp/y.jar. Then, when you run this on the command line:

java -jar /tmp/y.jar cool 

He prints:

 Hello darling Y! cool 

Example /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]); } } 

Example /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(); } } 

Example /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(); } } 
+5
source

Do you need to write it in plain old Java? I would use Gradle (a Groovy ). You may have a custom task for writing source files for Y (Groovy makes it easy to write template files). Gradle makes it easy to generate an executable jar.

If you really want to collapse your own from scratch, you will need to use ZipOutStream to archive the compiled files after calling javac via the Process API to compile the source.

Maybe a little more information on why you want to do this will help get better answers.

amuses

Lee

+2
source

To clarify Lee's answer, you need to compile the source first. You can use Process or you can use the code from tools.jar directly, as described here . Then write the MANIFEST.MF file and put it all together using ZipOutputStream as indicated.

+1
source

Step 1: figure out how to do this manually using the command line. Step 2: automate this by invoking the program from Java.

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

For step 1, I would suggest using ant - IDEs cannot always be automated. So, either write all the files with Java, or specify some of the ant configurations included as resources in the project.

0
source

All Articles