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