―Javaプログラミングの前提知識―
2001/7/13
javacコマンドを使いこなす |
今回の内容
|
![]() ![]() ![]() ![]() |
javacコマンドは、Javaプログラムが書かれているソースファイル(.javaファイル)を読み込んで、クラスファイル(.classファイル)を生成するツールです。ソースファイルからクラスファイルを生成することを、コンパイルするといいます。つまり、javacコマンドはJavaプログラムのソースファイルをコンパイルするツールです。このようなツールのことを一般にコンパイラと呼びます。Java言語のCompiler(コンパイラ)なので、javacという名前が付いています。
ソースファイルは、われわれが読んだり書いたりするものであり、クラスファイルは、Java Virtual Machine(Java VM)が内容を理解して、実行するものです。つまり、javacコマンドは、プログラマとJava
VMの間の仲介者であり、Javaでアプリケーションを作成するうえで、最も基本的で重要なツールの1つです。
![]() |
基本的なjavacコマンドの使い方 |
javacコマンドは基本的にDOSプロンプトまたはコマンドプロンプト上で実行します。 javacコマンドを実行するには、DOSプロンプトまたはコマンドプロンプトで、次のように入力します。
javac
上のように、ただjavacとだけ入力すると、javacコマンドの簡単な使い方が表示されます。
もし、簡単な使い方が表示されずに、javacは存在しないなどとエラーメッセージが表示された場合は、環境変数PATHの設定に誤りがある可能性があるので、環境変数PATHの値が正しいかどうか確認してください。
環境変数PATHが正しく設定されているのに、javacが存在しないとエラーメッセージが表示された場合は、次のように入力してみてください。
(Java 2 SDKをインストールしたディレクトリ)\bin\javac
例えば、Java 2 SDKをディレクトリC:\jdk1.3にインストールした場合は、次のように入力します。
C:\jdk1.3\bin\javac
それでもjavacが存在しないというエラーメッセージが表示されるときは、インストールが失敗している可能性があります。また、javacコマンドの簡単な使い方が表示された場合は、環境変数PATHの設定を間違えていないか確認してください。
![]() |
ソースファイルをコンパイルする方法 |
ソースファイルをコンパイルする方法は簡単で、そのソースファイル名をjavacコマンドに指定するだけです。例えば、ソースファイルWordProcessor.javaをコンパイルするには、次のように入力します。
javac WordProcessor.java
WordProcessor.javaが正しいJava言語で書かれていれば、javacはクラスファイルWordProcessor.classを生成します。 javacコマンドは複数のソースファイルを同時にコンパイルすることもできます。例えば、ソースファイルWordProcessor.javaとScheduler.javaを同時にコンパイルするには、以下のように、ソースファイル名を並べて入力します。
javac WordProcessor.java Scheduler.java
また、javacコマンドではワイルドカードを用いてソースファイルを指定することもできます。 例えば、カレントディレクトリ内のすべてのソースファイルをコンパイルするには、次のように入力します。
javac *.java
javacコマンドを実行して、ソースファイルをコンパイルしようとしたのに、クラスファイルが生成されず、エラーメッセージが表示される場合があります。このようにコンパイルが失敗する理由は2つ考えられます。
第1に考えられる理由は、ソースファイルに誤りがあることです。エラーメッセージを参考にして、ソースファイルをもう1度読み直し、誤りがあれば、正しく書き直します。
第2に考えられる理由は、クラスパスの指定が間違っていることです。ソースファイルが参照しているクラスのクラスファイルがクラスパスに存在していない場合にも、クラスファイルは生成されません。このときは、必要なクラスファイルをjavacが見つけられるように、クラスパスを指定してください。例えば、コンパイルしようとしているソースファイルWordProcessor.java中で、クラスライブラリ(特定の目的のために用いられるクラスの集まりのこと)C:\lib\SpellChecker.jarが用いられている場合には、javacコマンドを実行するときに、-classpathオプションを用いて、
javac -classpath .:C:\lib\SpellChecker.jar WordProcessor.java
のように入力して、クラスライブラリをクラスパスに指定しなければなりません。なお、標準システムクラスライブラリや、エクステンション(拡張)メカニズムでインストールしたクラスライブラリを利用する場合には、それらのクラスへのクラスパスを指定する必要はありません。詳しくは、「クラスパス(class
path)を正しく使う」、「エクステンション(拡張)メカニズムとは」を参照してください。
![]() |
依存関係にあるソースファイルの |
javacはファイル間の依存関係を、あくまで簡単にですが、把握し、ソースファイルを自動的にコンパイルします。以下では、その仕組みについて説明します。
まず、javacは、直接コンパイルするよう指定されたソースファイルを解析し、そのソースファイル中で、どんなクラスが使用されているかを調べます。
次に、javacはソースファイル中に使われているクラスを検索します。javacはJava VMのように、ブートクラスパス、エクステンション(拡張)ディレクトリ、クラスパスの順に、クラスファイルを検索しますが、それに加えソースパスを検索し、検索しているクラスに対応するソースファイルがないかどうか調べます。ソースパスについては、オプション-sourcepathの説明を参照してください。
検索の結果、 もし、クラスファイルのみ見つかり、ソースファイルが見つからなかった場合は、単にそのクラスファイルを利用します。もし、ソースファイルのみ見つかり、クラスファイルが見つからなかった場合は、見つかったソースファイルをコンパイルします。
もし、クラスファイルもソースファイルも見つかった場合は、ソースファイルを最後に変更した時刻とクラスファイルを最後に変更した時刻とを比較し、 ソースファイルを最後に変更した時刻がクラスファイルを最後に変更した時刻よりも後であるなら、javacは、クラスファイルがコンパイルされた後に、ソースファイルが変更されたと考えて、そのソースファイルをコンパイルします。
逆に、クラスファイルを最後に変更した時刻がソースファイルを最後に変更した時刻よりも後であるなら、単にそのクラスファイルを利用します。
以上のように、javacは、直接指定されたソースファイルと依存関係にあるソースファイルをある程度自動的にコンパイルします。例えば、以下の2つのソースファイル、Car.javaとEngine.javaを書いて、コンパイルすることを考えてみます。
public class Car { public Engine engine; } |
Car.java: |
public class Engine { } |
Engine.java: |
ここで、
javac Car.java
と、javacコマンドにソースファイルCar.javaをコンパイルするように指定すると、javacはソースファイルEngine.javaもコンパイルします。
このときのjavacの動作は以下のとおりです。まず、javacはソースファイルCar.javaを解析します。すると、ソースファイルCar.javaの中で、クラスEngineが利用されていることが分かります。次に、javacはクラスEngineを検索します。具体的には、クラスファイルEngine.classとソースファイルEngine.javaを探します。この場合、クラスファイルは存在せず、ソースファイルEngine.javaのみ存在するので、javacはソースファイルEngine.javaをコンパイルします。
ソースファイルEngine.javaを以下のように書き直したとします。
public class Engine {
public int horsepower; } |
Engine.java |
ここで、
javac Car.java
と入力すると、やはり、ソースファイルEngine.javaもコンパイルされます。
このときのjavacの動作は以下のとおりです。まず、javacはソースファイルCar.javaを解析します。すると、ソースファイルCar.javaの中で、クラスEngineが利用されていることが分かります。次に、javacはクラスEngineを検索します。具体的には、クラスファイルEngine.classとソースファイルEngine.javaを探します。今度は、クラスファイルEngine.classもソースファイルEngine.javaも存在しますので、javacはそれらの最終変更時刻を比べます。この場合は、ソースファイルEngine.javaの最終変更時刻の方が後なので、javacはソースファイルEngine.javaをコンパイルします。
以上のように、javacはある程度の依存関係を考慮し、依存関係にあるソースファイルが更新されている場合に、そのソースファイルを自動的にコンパイルします。
しかし、javacによる更新されたソースファイルの自動コンパイルは、非常に単純なものですので、上のようにうまくいく例は極めてまれです(ソースファイルが3つ以上になると、うまく動作しません)。
ですので、この機能には頼らず、更新したソースファイルはjavacでコンパイルした方が無難です。
![]() |
javacコマンドのコマンドラインオプション |
●クラスパスを指定する
-classpath <クラスパス> |
javacがソースファイルをコンパイルするときに参照すべきクラスパスを指定するために用います。例えば、第三者が作成したクラスライブラリを利用するようなプログラムを書いた場合、そのクラスライブラリをここで指定する必要があります。クラスパスについては、"クラスパス(class path)とは何ですか"を参照してください。ちなみに、このオプションを指定しない場合は、クラスパスはカレントディレクトリに設定されます |
●クラスファイルの生成先を指定する
-d <ディレクトリ名> |
javacに、クラスファイルを<ディレクトリ名>で指定したディレクトリに生成させるために用います |
●ソースファイルを検索するパスを指定する
-sourcepath <ソースパス> |
javacがソースファイルを検索するパスを指定するために用います。このオプションを指定しない場合は、javacはソースファイルをカレントディレクトリから探します。なお、ソースパスの指定方法は、クラスパスの指定方法と同じです |
●デバッグ情報をクラスファイルに追加する
-g:<キーワード(のリスト)> |
デバッグ情報をクラスファイルに追加するためのオプションです。-g:sourceと指定すると、javacはソースファイルのデバッグ情報をクラスファイルに追加します。 -g:linesと指定すると、javacはソースファイル中の行番号のデバッグ情報をクラスファイルに追加します。 -g:varsと指定すると、javacはローカル変数のデバッグ情報をクラスファイルに追加します。 複数種類のデバッグ情報をjavacに生成させるためには、-g:の後ろのキーワードを“,”で区切ります。例えば、ソースファイルの情報と、ローカル変数の情報を生成させるためには、 -g:source,varsのように指定します。単に-gと指定すると、すべてのデバッグ情報がクラスファイルに追加されます。-g:noneと指定すると、javacはデバッグ情報を生成しません。 -gオプションを指定しない場合、javacはソースファイルの情報と、そのソースファイルの行番号の情報をクラスファイルに追加します。つまり、-g:lines,sourceと指定したのと同じ動作をします。 |
●クラスファイルの最適化(現在は無効)
-O |
このオプションを指定すると、javacは、クラスファイルを最適化、つまりより効率よく実行できるようにクラスファイルを生成する…ということになっているのですが、現在は、-Oオプションは無効です。つまり、-Oオプションを指定しても、javacの生成するクラスファイルは変化しません |
●警告を出力しない
-nowarn |
このオプションを指定すると、javacは警告(Warning)メッセージを出力しなくなります |
●コンパイル情報を表示する
-verbose |
このオプションを指定すると、javacが実際にどのような作業を行っているかを知ることができます。具体的には、どのソースファイルをコンパイルしているか、どのクラスファイルを読み込んだか、などの情報が表示されます |
●推奨されないメンバやクラスを表示する
-deprecation |
このオプションを指定すると、javacは、ソースファイル中に存在する、推奨されないメンバやクラスについて、その詳細を表示します。 推奨されないメンバやクラスとは、何らかの問題があるために、将来のクラスライブラリの実装ではサポートされないような、メンバやクラスのことです。そのため、推奨されないメンバやクラスを用いたプログラムは、将来のJava VM上では実行できなくなる可能性があります。 このオプションを指定しない場合は、javacは推奨されないメンバやクラスが、ソースファイル中に存在することのみを報告します。 |
●ブートクラスパスを指定する
-bootclasspath <ブートクラスパス> |
このオプションは、ブートクラスパスを指定するために用います。ブートクラスパスには標準システムライブラリへのパスを指定します。ブートクラスパスについては、「クラスパス(class path)を正しく使う」を参照してください。 通常はこのオプションを指定する必要はありません |
●エクステンションディレクトリを指定する
-extdirs <エクステンション(拡張)ディレクトリ> |
このオプションは、エクステンションメカニズムの、エクステンションディレクトリを指定するために用います。エクステンションメカニズムについては、「エクステンション(拡張)メカニズムとは」を参照してください。通常はこのオプションを指定する必要はありません |
●実行できるJavaのバージョンを指定する
-target <バージョン> |
このオプションは、クラスファイルがどのバージョンのJava VMで実行できるようにするかを指定します。指定できるバージョンは、1.1、1.2、1.3の3種類です。 1.1を指定すると、バージョン1.1以降のすべてのJava VMで実行できるクラスファイルが生成されます。-targetオプションを指定しなかった場合は、javacは-targetに1.1を指定したのと同じ動作をします。 1.2を指定すると、バージョン1.2以降のJava VMで実行できるクラスファイルが生成されます。 1.3を指定すると、バージョン1.3以降のJava VMで実行できるクラスファイルが生成されます。 通常はこのオプションを指定する必要はありません。 |
●エンコーディングを指定する
-encoding <エンコーディング指定> |
このオプションは、ソースファイルがどのような種類のエンコードで書かれているかを、javacに教えるために用います。このオプションを指定しなければjavacは、オペレーティングシステムの標準の文字コードを使用しているものとして、ソースファイルをコンパイルします。通常はこのオプションを指定する必要はありません |
(補足説明)
-bootclasspath/ -extdirs/ -targetなどのオプションは、ほかのバージョンやほかの仕様のJava VM上で実行するクラスファイルを生成するときに用います。例えば、JDK1.1などの古いJava
VM上や、携帯電話上で動作するようなJava VMで実行するクラスファイルを生成したい場合などにこのオプションが使われます。
![]() |
- 実運用の障害対応時間比較に見る、ログ管理基盤の効果 (2017/5/9)
ログ基盤の構築方法や利用方法、実際の案件で使ったときの事例などを紹介する連載。今回は、実案件を事例とし、ログ管理基盤の有用性を、障害対応時間比較も交えて紹介 - Chatwork、LINE、Netflixが進めるリアクティブシステムとは何か (2017/4/27)
「リアクティブ」に関連する幾つかの用語について解説し、リアクティブシステムを実現するためのライブラリを紹介します - Fluentd+Elasticsearch+Kibanaで作るログ基盤の概要と構築方法 (2017/4/6)
ログ基盤を実現するFluentd+Elasticsearch+Kibanaについて、構築方法や利用方法、実際の案件で使ったときの事例などを紹介する連載。初回は、ログ基盤の構築、利用方法について - プログラミングとビルド、Androidアプリ開発、Javaの基礎知識 (2017/4/3)
初心者が、Java言語を使ったAndroidのスマホアプリ開発を通じてプログラミングとは何かを学ぶ連載。初回は、プログラミングとビルド、Androidアプリ開発、Javaに関する基礎知識を解説する。
![]() |
|
|
|
![]() |