La commande' java ' compile-t-elle des programmes Java?


La plupart des sites Web sur Internet disent:

"utilisez la commande javac pour compiler un fichier .java. Ensuite, exécutez-le en utilisant la commande java"

, 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 commande javac, il s'exécute sans erreurs.

$ java hello.java
hello world

La commande java compile-t-elle également le programme? Si oui, pourquoi avons-nous besoin de la commande javac?

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)
Author: LogicalBranch, 2019-09-24

4 answers

Avant de Java 11, pour exécuter votre code, vous devez d'abord le compiler, puis vous pouvez l'exécuter. Voici un exemple:

javac test.java
java test

Depuis Java 11, vous pouvez toujours faire javac + java, ou vous pouvez exécuter java par lui-même pour compiler et exécuter automatiquement votre code. Notez qu'aucun fichier .class ne sera généré. Voici un exemple:

java test.java

Si vous exécutez java -help, vous verrez les différentes utilisations autorisées. Voici à quoi ça 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".

$ java -help
Usage: java [options] <mainclass> [args...]
           (to execute a class)
   or  java [options] -jar <jarfile> [args...]
           (to execute a jar file)
   or  java [options] -m <module>[/<mainclass>] [args...]
       java [options] --module <module>[/<mainclass>] [args...]
           (to execute the main class in a module)
   or  java [options] <sourcefile> [args]
           (to execute a single source-file program)

Mise à JOUR:

Comme l'a souligné @ BillK, OP a également demandé:

pourquoi avons-nous besoin de la commande javac?

La raison pour laquelle nous avons besoin de javac est de créer des fichiers .class afin que le code puisse être créé, testé, distribué, exécuté, partagé, etc. comme il l'est aujourd'hui. La motivation pour JEP 330 était de rendre plus facile pour "les premières étapes de l'apprentissage de Java, et lors de l'écriture de petits programmes utilitaires" sans changer toute autre utilisation existante.

 190
Author: kaan, 2019-09-28 02:51:48

Si vous utilisez Java 11, il existe une nouvelle fonctionnalité qui permet l'exécution d'un fichier source unique. Le compilateur source unique est plus promiscuous en termes de nom de classe par rapport au nom de fichier, c'est ainsi que vous pouvez exécuter mais pas compiler avec succès.

Si vous êtes sur une version précédente de Java,, puis votre bonjour.java ne compile pas, en raison d'erreurs de compilation, en particulier autour du nom de classe. Il n'y a donc absolument aucun moyen d'appeler java hello.Java compilé 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.

 52
Author: Evan, 2019-09-25 18:03:46

Pour répondre pourquoi cette erreur est donnée, le nom de classe du fichier doit correspondre à basename du fichier.

, Vous avez deux options pour que ce code fonctionne pour le traditionnel javac; java séquence:

  1. Renommez la classe public class Hello ou

  2. Renommer hello.java à myclass.java.

L'interpréteur java pour Java 11 n'impose pas cette exigence. La classe qui contient main peut avoir n'importe quel nom, tant qu'il s'agit de la première classe du fichier. Cela a été principalement destiné à faciliter le processus d'apprentissage pour les débutants, et à permettre le "script java" avec le shebang (ref.).

 6
Author: S.S. Anne, 2019-09-27 22:44:09

Oui, mais pas de la façon dont vous voulez probablement dire.

Lorsque vous utilisez la commande javac pour compiler un .java fichier .fichier de classe la sortie est quelque chose appelé bytecode. Bytecode est un code machine (instructions natives) pour un processeur théorique basé sur la spécification de la machine virtuelle Java.

Cette spécification de CPU virtuel est une sorte de moyenne des types de PROCESSEURS qui étaient communs au moment où la spécification a été écrite. De ce fait, il est proche de beaucoup de différents types de CPU rendant plus facile d'exécuter le même Java .fichiers de classe sur plusieurs types de CPU.

Lorsque Java a été lancé pour la première fois, la commande java lirait le .class file et interpréter les instructions de bytecode une à la fois, puis les mapper à l'instruction native équivalente pour le PROCESSEUR sur lequel il s'exécutait réellement. Cela a fonctionné mais n'a pas été particulièrement rapide. Pour améliorer cela, la compilation Just in Time (JIT) a été ajoutée au Runtime Java.

Avec JIT, la commande java prend le bytecode et compile à nouveau les instructions natives pour le PROCESSEUR sur lequel il s'exécute. Les runtimes Java modernes ont tendance à commencer à interpréter le bytecode pendant la compilation JIT en arrière-plan et à passer aux instructions natives compilées lorsqu'elles sont prêtes et 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.

MODIFIER (pour apaiser les électeurs vers le bas):

Donc dans votre cas spécifique (car vous exécutez un JRE plus récent que v11) le code est compilé (au moins) deux fois

  1. En tant que single .fichier java en bytecode
  2. Via le compilateur JIT car il interprète le bytecode (bien que pour HelloWorld, il pourrait ne pas avoir le temps d'exécuter le code natif compilé)
 5
Author: hardillb, 2019-09-27 08:35:55