在运行时生成可执行jar

Bri*_*ris 4 java jar

我想编写一个可以在运行时创建可执行jar的Java应用程序.我想做的"hello world"是编写一个Java app X,在运行时生成一个可执行的jar Y,在运行时打印hello world(或者在Y运行之前可能还有另一个字符串未知).

我怎么能做到这一点?

Bri*_*ris 6

其他答案需要开始一个新的过程,这是一个没有的方法.以下是3个类定义,它们产生问题中描述的hello world场景.

运行XMain.main时,它会生成/tmp/y.jar.然后,当您在命令行运行它时:

java -jar /tmp/y.jar cool
Run Code Online (Sandbox Code Playgroud)

它打印:

Hello darling Y!
cool
Run Code Online (Sandbox Code Playgroud)

例如/ 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]);
    }
}
Run Code Online (Sandbox Code Playgroud)

例如/ 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

例如/ 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();
    }
}
Run Code Online (Sandbox Code Playgroud)