Java 在运行时生成可执行jar
我想写一个Java应用程序,它可以在运行时创建可执行的JAR。我想做的“hello world”是编写一个Java应用程序X,在运行时生成一个可执行的jar Y,在运行时打印hello world(或者可能是另一个直到Y运行后才知道的字符串)Java 在运行时生成可执行jar,java,jar,Java,Jar,我想写一个Java应用程序,它可以在运行时创建可执行的JAR。我想做的“hello world”是编写一个Java应用程序X,在运行时生成一个可执行的jar Y,在运行时打印hello world(或者可能是另一个直到Y运行后才知道的字符串) 我如何才能做到这一点?您必须用普通的旧Java编写它吗?我会使用(基于构建的工具)。您可以有一个自定义任务来为Y写出源文件(Groovy使写出模板文件变得非常容易)。Gradle使生成可执行jar变得很容易 如果你真的想从头开始,你需要在通过过程API调用
我如何才能做到这一点?您必须用普通的旧Java编写它吗?我会使用(基于构建的工具)。您可以有一个自定义任务来为Y写出源文件(Groovy使写出模板文件变得非常容易)。Gradle使生成可执行jar变得很容易 如果你真的想从头开始,你需要在通过过程API调用javac编译源代码后使用ZipOutStream来压缩编译后的文件 也许多了解一点你为什么要这么做会有助于得到更好的答案 干杯
Lee第1步:了解如何使用命令行手动执行此操作。 步骤2:通过在Java中调用程序来实现自动化
对于步骤1,我建议使用ant-IDE并不总是可以自动化的。因此,要么写出Java中的所有文件,要么将一些ant配置作为参考资料包含在项目中。要详细说明Lee的回答,您需要首先编译源代码。您可以使用Process,也可以直接使用
tools.jar
中的代码。然后写出一个MANIFEST.MF文件,并使用前面提到的ZipOutputStream将其放在一起。其他答案需要启动一个新的流程,这是一种不需要的方法。下面是3个类定义,它们生成问题中描述的hello world场景
运行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]);
}
}
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();
}
}
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();
}
}
示例/XMain.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]);
}
}
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();
}
}
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();
}
}
示例/Util.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]);
}
}
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();
}
}
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();
}
}
但你可以做得更好。Java编译和JAR文件创建步骤都可以在当前的JVM中完成,这正是我所希望的。除了安装JRE之外,我不想产生新的进程或依赖于主机的环境。斯蒂芬,你有一个例子的链接吗?