Создание автономного исполняемого файла Java для разных платформ без установки

Я создал образ среды выполнения Java-приложения, используя jlink. Я хотел бы иметь возможность отправлять программное обеспечение в виде исполняемого файла на разные платформы. (Предпочтительно путем сборки на одной платформе, например, путем кросс-компиляции.)

В идеале это должен быть один файл приложения, который пользователи могут запускать двойным щелчком, ничего не устанавливая.

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


person NeradaXsinZ    schedule 25.01.2019    source источник
comment
Вероятно, вам следует взглянуть на jpackager. jlink также может делать то, что вы хотите.   -  person ZhekaKozlov    schedule 26.01.2019
comment
См. варп-упаковщик. Сообщение в моем блоге Пишите один раз, стройте где угодно описывает решение. Дополнительные сведения см. в сценарии установщика для моего текстового редактора. MacOS тоже должна быть возможна. На странице релизы распространяются автономные двоичные файлы Windows и Linux. Нет установщика: дважды щелкните, чтобы запустить.   -  person Dave Jarvis    schedule 10.05.2021


Ответы (4)


Вы можете создать установщик, который устанавливает JDK и приложение. Сделайте приложение исполняемым с помощью чего-то вроде Launch4j, а для исполняемого файла Mac следуйте этому руководству от Oracle: Упаковка приложения Java для распространения на Mac и наконец: Для Linux

Minecraft использует этот метод, и пока я не знаю другого способа.

Если вы хотите создать переносимое приложение, создайте однократное запуск приложения в любом месте, тогда я бы предложил попробовать другой язык программирования, такой как C #, который также требует среды выполнения .NET, но встроен в системы Windows, тогда как Java необходимо устанавливать вручную.

person DudeManGuy    schedule 25.01.2019
comment
В основном правда, насколько я знаю. Нет возможности сделать исполняемый файл, всегда требуется JVM. Установщик, который автоматизирует некоторые шаги по установке JVM и любых необходимых библиотек, максимально близок к OP. - person markspace; 26.01.2019
comment
@Strom Да, Launch4j создает только исполняемые файлы, которые работают только в Windows. Что-то вроде этого, что делает исполняемые файлы Mac (файл DMJ), вероятно, существует. - person DudeManGuy; 26.01.2019
comment
В вашем сообщении содержится отличная информация о том, как упаковать приложение Java, чтобы обеспечить запуск приложения Java двойным щелчком как в Windows, так и в Mac OS без установленной среды выполнения JRE. - person Strom; 26.01.2019
comment
Ну, у меня есть портативный дистрибутив java и python. Если бы я создал программу только с относительными путями, вы могли бы просто скопировать все дерево папок, содержащее исполняемый файл, и оно работало бы на любой ОС Windows x64. Я использую его с USB @ работы. Это аккуратно, особенно с Python и PIP. Но кому нужна папка размером в несколько ГБ, когда на самом деле можно просто установить runtime-библиотеки? - person RoyM; 26.01.2019
comment
@RoyM, Java стала несовместимой сама с собой в разных версиях, и только одна версия может быть активна для всей системы одновременно. Это приводит к тому, что одни программы работают, а другие не работают. Используя Jlink, программы могут работать независимо от установленной версии. - person Strom; 26.01.2019

Двойной щелчок для запуска исполняемых файлов на нескольких платформах требует предварительной регистрации типа файла в операционной системе или существующего типа файла, чтобы знать, как обрабатывать код.

jlink статически связывает «необходимые модули и их транзитивные зависимости» с выходными данными.

У этой проблемы нет межплатформенного решения.

Маловероятно (или, другими словами, невозможно) включить все платформы в один файл, поскольку каждый исполняемый тип (COFF, ELF...) имеет различную структуру. Вы можете попытаться использовать общий пакетный файл для запуска правильного исполняемого файла, но в Windows для этого потребуется кодировка типа текстового файла; тем самым отравляя оставшийся двоичный код.

Использование jlink и нового формата файла jmod позволит вам хранить собственный код в контейнере Java и, таким образом, обеспечит точку входа во встроенный собственный код JRE в одном исполняемом образе для одного предварительного -определенная платформа.

Другая сторона этого вопроса связана с безопасностью. Поскольку встроенная JRE не подлежит обновлениям безопасности, взломщики могут внедрить ранее известную ошибочную JRE, тем самым раскрывая исправленные эксплойты неосведомленным потребителям.

Ожидаемым ответом антивирусных программ будет пометка всех необновленных встроенных JRE как вирусов.

person Strom    schedule 25.01.2019
comment
Я бы не назвал это статической компоновкой — это скорее упаковка всего в один файл. - person Robert; 26.01.2019
comment
На самом деле jlink позволяет запускать приложение без установки Java. Это его основная цель. - person ZhekaKozlov; 26.01.2019
comment
@ZhekaKozlov, Если это было его основной целью, почему нет прямых вариантов, на какую ОС он нацелен? Без файла jmod со встроенным собственным кодом jlink сам по себе не может создать собственный исполняемый файл. - person Strom; 28.01.2019
comment
@Robert, статическое связывание - это результат того, что компоновщик копирует все библиотечные процедуры, используемые в программе, в исполняемый образ. Это может потребовать больше места на диске и памяти, чем динамическая компоновка, но это быстрее и более переносимо, поскольку не требует наличия библиотеки в системе, где она выполняется. Цитата из kb.iu.edu/d/akqn. Поскольку каждая официальная реализация Java использовала динамическое связывание во время выполнения до jlink, как бы вы это назвали? - person Strom; 28.01.2019
comment
@Strom Это просто упаковка: один исполняемый файл с данными после окончания исполняемого файла точно так же, как самораспаковывающиеся установщики. Статическая компоновка включает в себя компоновщик, но здесь это просто данные вне исполняемого файла, но в том же файле. - person Robert; 28.01.2019
comment
@Strom Статическое связывание байт-кода Java !!? Я думаю, что мы должны остановиться здесь, прежде чем вы опубликуете больше этих запутанных утверждений... - person Robert; 30.01.2019

Также взгляните на SubstrateVM. Это не настоящая Java, однако она может помочь вам в некоторых случаях, например, в простых приложениях командной строки.

Substrate VM — это инфраструктура, которая позволяет заблаговременно (AOT) компилировать Java-приложения в условиях закрытого мира в исполняемые образы или общие объекты (ELF-64 или 64-разрядный Mach-O).

person ZhekaKozlov    schedule 28.01.2019

Да, начиная с Java 8, есть два способа сделать это: с помощью инструмента javapackager или с помощью Ant Tasks JavaFX (которые на самом деле не относятся к JavaFX и поставляются с Java 8 JDK).

Вот пример упаковки приложения в виде Jar, установки атрибутов main-class и classpath и копирования всех зависимостей в папку с помощью Maven.

<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>

А вот файл сборки Ant для упаковки автономного приложения (exe для Windows, .app и .dmg для OS X, .deb и .rpm для Linux).

<?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>
person guymac    schedule 04.06.2020