La plupart des sites Web sur Internet disent:
"utilisez la
javac
commande pour compiler un.java
fichier. Puis exécutez-le en utilisant lajava
commande"
Mais aujourd'hui, j'ai essayé d'exécuter un programme java sans javac
et j'ai obtenu un résultat étrange.
Voici le contenu d'un fichier appelé hello.java
:
public class Myclass {
public static void main(String[] args){
System.out.println("hello world");
}
}
Puis j'ai couru:
$ javac hello.java
Ce qui me donne cette erreur:
hello.java:1: error: class Myclass is public, should be declared in a file named Myclass.java
public class Myclass {
^
1 error
Mais quand je l'exécute sans la javac
commande, il s'exécute sans aucune erreur.
$ java hello.java
hello world
La java
commande compile- t-elle également le programme? Si oui, pourquoi avons-nous besoin de la javac
commande?
La version de mon java est:
openjdk version "12.0.2" 2019-07-16
OpenJDK Runtime Environment (build 12.0.2+10)
OpenJDK 64-Bit Server VM (build 12.0.2+10, mixed mode)
Myclass.java
puis à partir de la ligne de commande, compilez-le comme cecijavac Myclass.java
, puis exécutez-le comme cecijava Myclass
.javac
toujours utilisé pour compiler si vous ne voulez pas déployer le code source, ou si vous avez plus d'un seul fichier ( documentation de l'java
option for source-file: Uniquement utilisé pour lancer un seul programme de fichier source.)javac
compile la source Java dans le bytecode interprété spécifique à la JVM et lajava
commande le charge dans le ClassLoader de la JVM.Réponses:
Avant Java 11, pour exécuter votre code, vous devez d'abord le compiler, puis vous pouvez l'exécuter. Voici un exemple:
Depuis Java 11, vous pouvez toujours faire
javac
+java
, ou vous pouvez exécuterjava
par lui-même pour compiler et exécuter automatiquement votre code. Notez qu'aucun.class
fichier ne sera généré. Voici un exemple:Si vous exécutez
java -help
, vous verrez les différentes utilisations autorisées. Voici à quoi cela ressemble sur ma machine. Le dernier est ce que vous avez rencontré:java [options] <sourcefile> [args]
qui "exécutera un seul programme de fichier source".METTRE À JOUR:
Comme l'a souligné @BillK, OP a également demandé:
La raison pour laquelle nous avons besoin
javac
est de créer des.class
fichiers afin que le code puisse être créé, testé, distribué, exécuté, partagé, etc., comme c'est le cas aujourd'hui. La motivation de JEP 330 était de faciliter les "premières étapes de l'apprentissage de Java, et lors de l'écriture de petits programmes utilitaires" sans changer les autres utilisations existantes.la source
1.
dans1.8
dans les versions plus récentes)javac
.Si vous exécutez Java 11, il existe une nouvelle fonctionnalité qui permet l'exécution d'un fichier source unique. Le compilateur source unique est plus promiscuité en termes de nom de classe que de nom de fichier, c'est ainsi que vous pouvez exécuter mais pas compiler avec succès.
Si vous utilisez une version précédente de Java, votre hello.java actuel ne se compile pas, en raison d'erreurs de compilation, en particulier autour du nom de la classe. Il n'y a donc absolument aucun moyen d'appeler java hello.java pour compiler votre code, car il ne compile pas.
Il semble très probable que vous exécutiez du code précédemment compilé lors de l'exécution de la commande java.
la source
Pour expliquer pourquoi cette erreur est donnée, le nom de classe du fichier doit correspondre à celui du fichier
basename
.Vous avez deux options pour que ce code fonctionne pour le traditionnel
javac
;java
séquence:Renommez la classe en
public class Hello
ouRenommez
hello.java
enmyclass.java
.L'
java
interpréteur pour Java 11 n'impose pas cette exigence. La classe qui contientmain
peut avoir n'importe quel nom, à condition qu'il s'agisse de la première classe du fichier. Cela visait principalement à faciliter le processus d'apprentissage pour les débutants, et à permettre le "script java" avec le shebang ( réf. ).la source
Oui, mais pas de la façon dont vous l'entendez probablement.
Lorsque vous utilisez la
javac
commande pour compiler un fichier .java dans un fichier .class, la sortie est quelque chose appelé bytecode. Bytecode est un code machine (instructions natives) pour un processeur théorique basé sur la spécification Java Virtual Machine.Cette spécification de CPU virtuelle est en quelque sorte une moyenne des types de CPU qui étaient courants au moment où la spécification a été écrite. Pour cette raison, il est proche de nombreux types de processeurs différents, ce qui facilite l'exécution des mêmes fichiers Java .class sur plusieurs types de processeurs.
Lorsque Java était lancé pour la première fois, la
java
commande lisait le fichier .class et interprétait les instructions de bytecode une par une, puis les mappait à l'instruction native équivalente pour le processeur sur lequel elle s'exécutait réellement. Cela a fonctionné mais n'était pas particulièrement rapide. Pour améliorer cette compilation Just in Time (JIT) a été ajoutée au Java Runtime.Avec JIT, la
java
commande prend le bytecode et le compile à nouveau dans les instructions natives du processeur sur lequel il s'exécute. Les environnements d'exécution Java modernes ont tendance à commencer à interpréter le bytecode pendant la compilation JIT en arrière-plan et à basculer vers les instructions natives compilées lorsqu'il est prêt.Ils profileront également l'application en cours d'exécution, puis recompileront à nouveau le bytecode avec une optimisation différente pour obtenir les meilleures performances possibles.EDIT (pour apaiser les votants):
Donc, dans votre cas spécifique (comme vous exécutez un JRE plus récent que la v11), le code est compilé (au moins) deux fois
la source
mixed-mode
dans la sortie de la version