генерировать исполняемый файл jar во время выполнения - PullRequest
4 голосов
/ 07 января 2010

Я хотел бы написать приложение на Java, которое может создавать исполняемые файлы jar во время выполнения. «Здравствуй, мир» того, что я хочу сделать, - это написать Java-приложение X, которое при запуске генерирует исполняемый jar-файл Y, который при запуске печатает привет-мир (или, возможно, другую строку, неизвестную до тех пор, пока Y не будет запущен).

Как мне это сделать?

Ответы [ 4 ]

6 голосов
/ 23 января 2010

Другие ответы требуют запуска нового процесса, это метод, который не требует. Вот три определения классов, которые создают сценарий «Привет, мир», описанный в вопросе.

Когда вы запускаете XMain.main, он генерирует /tmp/y.jar. Затем, когда вы запустите это в командной строке:

java -jar /tmp/y.jar cool

Он печатает:

Hello darling Y!
cool

Пример / 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]);
    }
}

Пример / 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();
    }
}

Пример / 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 голосов
/ 07 января 2010

Вы должны написать это на простой старой Java? Я бы использовал Gradle (основанный на Groovy инструмент для сборки). У вас может быть пользовательская задача для записи исходных файлов для Y (Groovy позволяет действительно легко записывать шаблонные файлы). Gradle позволяет легко создать исполняемый файл.

Если вы действительно хотите свернуть свой собственный с нуля, вам нужно использовать ZipOutStream, чтобы сжать скомпилированные файлы после вызова javac через Process API для компиляции исходного кода.

Может быть, немного больше информации о том, почему вы хотите это сделать, поможет получить лучшие ответы

ура

Lee

1 голос
/ 07 января 2010

Чтобы уточнить ответ Ли, сначала нужно скомпилировать источник. Вы можете использовать Process или использовать код из tools.jar напрямую, как объяснено здесь . Затем запишите файл MANIFEST.MF и соедините все вместе, используя ZipOutputStream, как указано.

0 голосов
/ 07 января 2010

Шаг 1: выяснить, как это сделать вручную с помощью командной строки. Шаг 2: автоматизируйте это, вызывая программу из Java.

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

Для шага 1 я бы предложил использовать ant - IDE не всегда автоматизированы. Итак, либо запишите все файлы из Java, либо включите некоторые конфигурации ant в качестве ресурсов в проект.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...