web-dev-qa-db-ja.com

「Java」コマンドはJavaプログラムをコンパイルしますか?

インターネット上のほとんどのウェブサイトはこう言います:

"javacコマンドを使用して.Javaファイルをコンパイルします。その後、Javaコマンドを使用して実行します"

しかし、今日、javacなしでJavaプログラムを実行しようとしましたが、奇妙な結果が得られました。

hello.Javaというファイルの内容は次のとおりです。

public class Myclass {
 public static void main(String[] args){
    System.out.println("hello world");
  }
}

それから私は走った:

$ javac hello.Java

これは私にこのエラーを与えます:

hello.Java:1: error: class Myclass is public, should be declared in a file named Myclass.Java
public class Myclass {
       ^
1 error

しかし、javacコマンドなしで実行すると、エラーなしで実行されました。

$ Java hello.Java
hello world

Javaコマンドもプログラムをコンパイルしますか?はいの場合、なぜjavacコマンドが必要なのですか?

My Javaのバージョンは:

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)
144
milad

Java 11の前に、コードを実行するには、最初にコンパイルする必要があります。次に実行できます。以下に例を示します。

javac test.Java
java test

Java 11なので、まだjavac + Javaを実行できます。または、Javaを単独で実行してコンパイルし、自動実行することもできます。コード。.classファイルが生成されます。次に例を示します。

Java test.Java

Java -help、許可されたさまざまな使用法が表示されます。私のマシンでは次のようになります。最後のものは、あなたが遭遇したものです:Java [options] <sourcefile> [args]「単一のソースファイルプログラムを実行する」。

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

UPDATE:

@BillKが指摘したように、OPは次の質問もしました。

なぜjavacコマンドが必要なのですか?

javacが必要な理由は、.classファイル。これにより、現在のようにコードを作成、テスト、配布、実行、共有などすることができます。 JEP 3 の動機は、「Javaの学習の初期段階、および小さなユーティリティプログラムを記述するとき」を他の既存の用途を変更せずに簡単にすることでした。

187
kaan

実行している場合Java 11、単一ソースファイルの実行を許可する新しい機能があります。単一ソースコンパイラは、クラス名とファイル名の点でより無差別です。 、それはあなたが実行することができますが、正常にコンパイルできない方法です。

以前のバージョンのJavaを使用している場合の場合、現在のhello.Javaは、特にクラス名周辺のコンパイルエラーのためにコンパイルされません。したがって、コードをコンパイルしないため、Java hello.Javaを呼び出してコードをコンパイルする方法はまったくありません。

Javaコマンドを実行するときに、以前にコンパイルされたコードを実行していた可能性が最も高いようです。

52
Evan

このエラーが発生する理由に答えるには、ファイルのクラス名がファイルのbasenameと一致する必要があります。

このコードを従来のjavacに対して機能させるには、2つのオプションがあります。 Javaシーケンス:

  1. クラスの名前をpublic class Helloに変更するか、

  2. hello.Javaの名前をmyclass.Javaに変更します。

Java 11のJavaインタープリターは、この要件を課しません。mainを含むクラスは、それがこれは主に、初心者向けの学習プロセスを容易にし、シバンで「Javaスクリプト」を許可することを目的としています( ref。 )。

6
S.S. Anne

はい、しかしあなたがおそらく意味する方法ではありません。

javacコマンドを使用して.Javaファイルを.classファイルにコンパイルすると、出力はバイトコードと呼ばれるものになります。バイトコードは、Java Virtual Machineの仕様に基づいた理論上のCPUのマシンコード(ネイティブ命令)です。

この仮想CPU仕様は、仕様が作成された時点で一般的だったCPUの種類の平均のようなものです。このため、多くの異なるタイプのCPUに近いため、同じJava .classファイルを複数のCPUタイプで実行しやすくなります。

Javaが最初に起動されたとき、Javaコマンドは.classファイルを読み取り、バイトコード命令を一度に1つずつ解釈し、CPUの同等のネイティブ命令にマップしますジャストインタイム(JIT)コンパイルをJava Runtime。に追加しました。

JITを使用すると、Javaコマンドはバイトコードを取得し、実行中のCPUのネイティブ命令に再度コンパイルします。モダンJavaランタイムは、バックグラウンドでJITコンパイル中にバイトコードの解釈を開始し、準備ができたときにコンパイル済みネイティブ命令に切り替え、実行中のアプリケーションのプロファイルを作成し、別のバイトコードを再コンパイルします最高のパフォーマンスを得るための最適化。

編集(下の有権者をなだめるため):

したがって、特定の場合(v11より新しいJREを実行している場合)、コードは(少なくとも)2回コンパイルされます。

  1. バイトコードへの単一の.Javaファイルとして
  2. バイトコードを解釈するJITコンパイラ経由(helloWorldの場合、コンパイルされたネイティブコードを実行する時間を実際に取得できない場合があります)
5
hardillb