web-dev-qa-db-fra.com

Java 11: l'exécution du fichier source via Shebang ne fonctionne pas

Je voulais découvrir quelques nouvelles fonctionnalités de Java 11 qui a été publié il y a deux jours. JEP 3 déclare que je pouvais lancer un programme Java-Source-Code sans Il devrait également prendre en charge l'utilisation de Shebang-Files.

J'ai donc écrit ce petit programme Hello-World Test.Java:

#!/opt/Java/jdk-11/bin/Java --source 11

public class Test
{
    public static void main(String[] args)
    {
        System.out.println("Hello World!");
    }
}

I téléchargé JDK 11 et extrait à /opt/Java. Par conséquent, le Shebang lui-même fonctionne. C'est à dire. exécution /opt/Java/jdk-11/bin/Java --version Donne moi

openjdk 11 2018-09-25
OpenJDK Runtime Environment 18.9 (build 11+28)
OpenJDK 64-Bit Server VM 18.9 (build 11+28, mixed mode)

Après avoir fait Test.Java exécutable (en utilisant chmod +x Test.Java) l'exécution échoue. C'est à dire. ./Test.Java Donne moi:

./Test.Java:1: error: illegal character: '#'
#!/opt/Java/jdk-11/bin/Java --source 11
^
./Test.Java:1: error: class, interface, or enum expected
#!/opt/Java/jdk-11/bin/Java --source 11
^
2 errors
error: compilation failed

Dès que je retire la Shebang-Line de Test.Java et commencez par /opt/Java/jdk-11/bin/Java --source 11 Test.Java tout fonctionne comme un charme et j'obtiens la sortie attendue: Hello World!

Ma machine fonctionne Ubuntu 17.04. J'ai lié javac à celui du JDK 11 (c'est-à-dire en exécutant javac -version donne javac 11).

17
mam10eks

Le nom de fichier ne doit pas se terminer par .Java pour que l'exécutable Java ignore la ligne Shebang. Vous pouvez utiliser une extension différente, ou tout simplement ne pas avoir d'extension du tout (c'est ce qu'ils font dans l'exemple JEP et ce que je recommanderais).

De JEP 3 (italique ajouté):

Lorsque le lanceur lit le fichier source, si le fichier n'est pas un fichier source Java (c'est-à-dire qu'il ne s'agit pas d'un fichier dont le nom se termine par .Java) et si la première ligne commence par # !, le contenu de cette ligne jusqu'à mais sans inclure la première nouvelle ligne est ignoré lors de la détermination du code source à passer au compilateur. Le fichier qui apparaît après la première ligne doit être composé d'une unité de compilation valide telle que définie par le §7.3 dans l'édition de la spécification de langage Java Java appropriée à la version de la plate-forme indiquée dans la --source , le cas échéant, ou la version de la plate-forme utilisée pour exécuter le programme si l'option --source n'est pas présente.

Il ne doit pas nécessairement se terminer par ".sh"; cela est également potentiellement trompeur car le fichier n'est pas réellement un script Shell.

18
Miles

Un peu d'essais et d'erreurs m'a donné la bonne solution. C'était l'extension de fichier .Java ce qui cause ces problèmes.

C'est à dire. si je renomme le fichier en Test.sh tout fonctionne.

Voici un exemple complet de Hello-World-Shebang:

Créer un fichier Test.sh avec un contenu comme

#!/opt/Java/jdk-11/bin/Java --source 11

public class Test
{
    public static void main(String[] args)
    {
        System.out.println("Hello World!");
    }
}

Rendez-le exécutable (c'est-à-dire chmod +x Test.sh).

Enfin, exécutez-le en utilisant ./Test.sh

6
mam10eks

Selon le JEP auquel vous êtes lié (voir section Fichiers Shebang ), le fichier Shebang doit être utilisé pour lancer le processus Java, à ne pas utiliser comme paramètre pour Java:

Un fichier Shebang pour appeler le lanceur Java en utilisant le mode fichier source doit commencer par quelque chose comme:

#!/path/to/Java --source version

Par exemple, nous pourrions prendre le code source d'un programme "Hello World", et le mettre dans un fichier appelé hello, après une ligne initiale de #!/Path/to/Java --source 10, , puis marquez le fichier comme exécutable . Ensuite, si le fichier se trouve dans le répertoire courant, nous pourrions l'exécuter avec:

$ ./hello

En d'autres termes, ce que vous voulez faire, c'est plutôt faire Test.Java exécutable. Vous devrez également le renommer car il ne fonctionnera pas comme Shebang et supprimera la première ligne quand il sera nommé * .Java.

$ move Test.Java test
$ chmod +x test
$ ./test 

Cela lancera le processeur Shebang qui supprimera la première ligne et passera le reste du script à/path/to/Java et Java compilera le script et exécutera la méthode principale.

1
ernest_k