创建一个JAVA Standalone可执行应用程序,使其无需安装即可在不同平台上运行

时间:2019-01-25 20:56:33

标签: java package executable java-11

我已经使用jlink为我的Java应用程序创建了一个运行时映像,我希望能够将我的应用程序作为可执行文件发布到不同的平台。

理想情况下,它将是一个文件,用户可以双击该文件并启动应用程序,而无需安装任何程序。

目前是否有个好方法?

4 个答案:

答案 0 :(得分:2)

您可以制作一个用于安装JDK和应用程序的安装程序。通过使用诸如Launch4j之类的东西使该应用程序成为exe,对于Mac可执行文件,请遵循Oracle的本教程:Packaging a Java App for Distribution on a Mac,最后是For Linux

Minecraft使用这种方法,据我所知,没有其他方法。

如果要制作可移植的应用程序,使它“在任何地方运行一次”类型的应用程序,那么我建议尝试使用另一种编程语言,例如C#,它也需要.NET JVM,但已嵌入Windows系统中。

答案 1 :(得分:0)

双击以在多个平台上运行可执行文件,需要事先在操作系统中注册文件类型,或者需要现有文件类型才能知道如何处理代码。

jlink将“所需模块及其传递依赖项”静态链接到输出。

没有跨平台的解决方案。

将所有平台都包含在一个文件中是不可能的(或者用另一种方式,不可行),因为每种可执行文件类型(COFF,ELF ...)具有不同的结构。您可以尝试使用通用批处理文件来启动适当的可执行文件,但是在Windows上,这将需要文本文件类型编码。因此中毒了其余的二进制代码。

使用jlink 新的jmod文件格式将允许您将本机代码存储在Java容器中,从而允许在单个可执行映像中将嵌入的本地JRE代码的入口点一个预定义的平台。

此问题的另一面是安全隐患。由于嵌入式JRE不受安全更新的影响,因此破解者可以选择嵌入以前已知的有缺陷的JRE,从而将更正的漏洞暴露给用户。

反病毒程序的预期响应是将所有未更新的嵌入式JRE标记为病毒。

答案 2 :(得分:0)

是的,从Java 8开始,使用javapackager工具或JavaFX Ant Tasks(实际上并不是特定于JavaFX的,而是Java 8 JDK提供的)有两种方法。

下面是一个使用Maven将应用程序打包为Jar,设置main-class和classpath属性以及将所有依赖项复制到文件夹中的示例。

<plugins>
        <plugin>
            <artifactId>maven-dependency-plugin</artifactId>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>copy-dependencies</goal>
                    </goals>
                    <configuration>
                        <outputDirectory>${project.build.directory}/lib</outputDirectory>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <artifactId>maven-jar-plugin</artifactId>
            <version>3.2.0</version>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <mainClass>${project.groupId}.${project.artifactId}.DemoCLI</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
</plugins>

这是用于打包独立应用程序(Windows的exe,OS X的.app和.dmg,Linux的.deb和.rpm)的Ant构建文件。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xml>

<!--
 Uses the JavaFX Ant Tasks to build native application bundles
 (specific to the platform which it is built on).

 See https://docs.oracle.com/javase/8/docs/technotes/guides/deploy/javafx_ant_tasks.html

 These tasks are distributed with version 8 of the Oracle JDK,
 Amazon Corretto JDK, RedHat JDK, probably others, though they
 do not seem to be the OpenJDK on Debian Linux

 -->
<project
    name="fxwebclient" default="default" basedir="."
    xmlns:fx="javafx:com.sun.javafx.tools.ant">

    <!-- In Java 8, java.home is typically the JRE of a JDK -->
    <property name="jdk.lib.dir" value="${java.home}/../lib" />

    <!-- Where to build our app bundles -->
    <property name="build.dist.dir" value="${basedir}/target/dist" />

   <echo>Using Java from ${java.home}</echo>

    <target name="default" depends="clean">

        <!-- get the ant-jfx.jar from the JDK -->
        <taskdef resource="com/sun/javafx/tools/ant/antlib.xml"
            uri="javafx:com.sun.javafx.tools.ant"
            classpath="${jdk.lib.dir}/ant-javafx.jar" />

        <!-- Define our application entry point -->
        <fx:application id="demo" name="demo"
            mainClass="yourpackage.DemoCLI" />

        <!-- Our jar and copied dependency jars (see pom.xml) -->
       <fx:resources id="appRes">
            <fx:fileset dir="${basedir}/target" includes="*.jar"/>
            <fx:fileset dir="${basedir}/target/lib" includes="*.jar" />
       </fx:resources>

        <!-- Create app bundles [platform specific] -->
        <fx:deploy nativeBundles="all"
            outdir="${build.dist.dir}" outfile="DemoWebClient">

            <fx:application refid="demo" />
            <fx:resources refid="appRes" />

        </fx:deploy>

    </target>

    <!-- clean up -->
    <target name="clean">
        <delete dir="${build.dist.dir}" includeEmptyDirs="true" />
        <delete file="${basedir}/target/${ant.project.name}.jar" />
    </target>

</project>

答案 3 :(得分:-1)

另外,请查看SubstrateVM。这不是真正的Java,但是在某些情况下(例如简单的命令行应用程序)可能会为您提供帮助。

  

基板VM是允许提前(AOT)的框架   在封闭世界假设下将Java应用程序编译为   可执行映像或共享对象(ELF-64或64位Mach-O)。