9
votes

créer une application exécutable JAVA Standalone à exécuter sur différentes plates-formes sans aucune installation

J'ai créé une image d'exécution pour mon application Java à l'aide de jlink et j'aimerais pouvoir expédier mon application en tant qu'exécutable sur différentes plates-formes.

Idéalement, ce serait un seul fichier sur lequel un utilisateur peut double-cliquer et démarrer l'application sans avoir besoin d'installer quoi que ce soit.

Existe-t-il actuellement un bon moyen de procéder?


6 commentaires

Vous devriez probablement regarder jpackager . jlink peut également faire ce que vous voulez.


@ZhekaKozlov, Il n'y a pas de solution actuelle qui puisse fournir un seul fichier, qui peut être double-cliqué sur chaque plate-forme et exécuté.


@Strom Oui, il n'y a pas de solution. Mais pourquoi en auriez-vous besoin? Chaque application Java non triviale a plusieurs fichiers (images, ressources, bibliothèques dynamiques). Est-il même possible de les fusionner en un seul exécutable?


@ZhekaKozlov, je n'en ai pas besoin ni ne veux, c'est la question des OP, pas la mienne. Vous dans votre commentaire avez déclaré "regardez jpackager. Jlink peut aussi faire ce que vous voulez". Ce que veut l'OP n'est pas possible. Par conséquent, j'ai essayé de fournir la meilleure réponse au meilleur de ma connaissance. Ce qui s'est considérablement amélioré depuis le début de cette question.


@Strom L'OP a dit "Idéalement, ce serait un seul fichier" ce qui ne veut pas nécessairement dire. Donc, mon premier commentaire est un conseil tout à fait valable.


@ZhekaKozlov, je suis d'accord avec votre interprétation de Idéalement , mais les commentaires que vous avez fournis indiquent à OP que c'est possible et ne donnent aucune indication du contraire. Mais, nous débattons de sémantique ici et ce n'est pas le lieu pour cela.


4 Réponses :


5
votes

Vous pouvez créer un programme d'installation qui installe le JDK et l'application. Faites de l'application un exe en utilisant quelque chose comme Launch4j et pour un exécutable Mac, suivez ce tutoriel d'Oracle: Empaquetage d'une application Java pour distribution sur un Mac et enfin: Pour Linux

Minecraft utilise cette méthode et dans la mesure où je ne connais pas d'autre moyen.

Si vous voulez créer une application portable, tapez une application de type "faire une fois exécuter n'importe où", je vous suggère d'essayer un autre langage de programmation comme C # qui nécessite également le .NET Runtime mais est intégré aux systèmes Windows alors que Java doit l'être installé manuellement.


7 commentaires

Fondamentalement vrai pour autant que je sache. Il n'y a aucun moyen de "créer un exécutable", la JVM est toujours requise. Un programme d'installation qui automatise certaines des étapes d'installation d'une JVM et de toutes les bibliothèques nécessaires est aussi proche que l'OP peut l'obtenir.


@Strom Oui, Launch4j ne fait que des exes qui ne fonctionnent que sous Windows. Quelque chose comme ça qui rend les exécutables Mac (fichier DMJ) existe probablement.


C # nécessite également une machine virtuelle. Il se trouve juste qu'il est intégré à Windows;) Même dans ce cas, vos utilisateurs auront encore besoin "d'installer quelque chose" si leur .Net est obsolète.


Le fait est qu'il n'y a pas de moyen unique d'empaqueter une application multiplateforme qui peut être exécutée simplement en double-cliquant dessus.


Votre article contient des informations intéressantes sur la manière de créer un package d'une application Java pour activer le double-clic d'une application Java sur Windows et Mac OS sans que le JRE ne soit installé.


Eh bien, j'ai une distribution portable de java et python. Si je devais créer un programme avec uniquement des chemins relatifs, vous pourriez simplement copier une arborescence de dossiers entière, contenant l'exécutable, et vous le feriez fonctionner sur n'importe quel système d'exploitation Windows x64. Je l'utilise depuis un USB @ work. C'est chouette, surtout avec python et PIP. Mais qui veut un dossier de plusieurs Go alors qu'en réalité ils peuvent simplement installer des bibliothèques d'exécution?


@RoyM, Java est devenu incompatible avec lui-même d'une version à l'autre, et une seule version peut être active à la fois à l'échelle du système. Conduisant à l'exécution de certains programmes et à d'autres échecs. En utilisant Jlink, les programmes peuvent fonctionner quelle que soit la version installée.



0
votes

Double-cliquez pour exécuter des exécutables sur plusieurs plates-formes, nécessite l'enregistrement préalable du type de fichier avec le système d'exploitation, ou un type de fichier existant pour savoir comment gérer le code.

jlink relie statiquement les "modules requis et leurs dépendances transitives" à la sortie.

Il n'y a pas de solution multiplateforme à ce problème.

Il est improbable (ou pour le dire autrement, pas faisable) d'inclure toutes les plates-formes dans un seul fichier, puisque chaque type d'exécutable (COFF, ELF ...), a une structure différente. Vous pouvez essayer d'utiliser un fichier batch générique pour démarrer l'exécutable approprié, mais sous Windows, cela nécessiterait un codage de type fichier texte; empoisonnant ainsi le code binaire restant.

L'utilisation de jlink et le nouveau format de fichier jmod vous permettra de stocker du code natif dans un conteneur Java, et ainsi de permettre le point d'entrée dans le code JRE natif intégré dans une seule image exécutable pour une seule plate-forme prédéfinie.

L'autre aspect de ce problème concerne les implications en matière de sécurité. Étant donné que le JRE intégré n'est pas soumis à des mises à jour de sécurité, les pirates peuvent choisir d'intégrer un JRE défectueux précédemment connu, exposant ainsi les exploits corrigés à des consommateurs ignorants.

La réponse attendue des programmes antivirus serait de signaler tous les JRE intégrés non mis à jour comme des virus.


6 commentaires

Je ne l'appellerais pas " liaison statique " - il s'agit plutôt de regrouper tout dans un seul fichier.


En fait, jlink permet d'exécuter l'application sans que Java soit installé. C'est son objectif principal.


@ZhekaKozlov, Si tel était son "objectif principal", pourquoi n'y a-t-il pas d'options directes pour quel système d'exploitation cible-t-il? Sans un fichier jmod avec du code natif intégré, jlink seul ne peut pas créer un exécutable natif.


@Robert, "La liaison statique est le résultat de la copie par l'éditeur de liens de toutes les routines de bibliothèque utilisées dans le programme dans l'image exécutable. Cela peut nécessiter plus d'espace disque et de mémoire que la liaison dynamique, mais est à la fois plus rapide et plus portable, car elle ne nécessite pas la présence de la bibliothèque sur le système où elle est exécutée. " Extrait de " kb.iu.edu/d/akqn ". Étant donné que chaque implémentation officielle de Java a utilisé la liaison d'exécution / dynamique jusqu'à jlink, comment l'appeleriez-vous?


@Strom C'est juste un empaquetage: un exécutable avec des données après la fin de l'exécutable exactement comme les programmes d'installation auto-extractibles. La liaison statique incorporait un éditeur de liens, mais ici, il ne s'agissait que de données en dehors de l'exécutable mais dans le même fichier.


@Strom Liaison statique du bytecode Java !!? Je pense que nous devrions nous arrêter ici avant de publier plus de ces déclarations déroutantes ...



0
votes

Jetez également un œil à SubstrateVM . Ce n'est pas un vrai Java, cependant, cela peut vous aider dans certains cas comme de simples applications en ligne de commande.

Substrate VM est un framework qui permet à l'avance (AOT) compilation d'applications Java sous l'hypothèse d'un monde fermé en images exécutables ou objets partagés (ELF-64 ou Mach-O 64 bits).


0 commentaires

0
votes

Oui, à partir de Java 8, il existe deux façons de le faire, en utilisant l'outil javapackager ou les tâches Ant JavaFX (qui ne sont pas réellement spécifiques à JavaFX et sont fournis avec le JDK Java 8).

Voici un exemple d'empaquetage d'une application en tant que Jar, de définition des attributs de classe principale et de chemin de classe, et de copie de toutes les dépendances dans un dossier, en utilisant Maven.

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

Et voici le fichier de construction Ant pour empaqueter l'application autonome (exe pour Windows, .app et .dmg sous OS X, .deb et .rpm sous Linux).

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


0 commentaires