JDKTM 1.1 ツールと JavaTM 2 SDK ツールの
|
SDK ツール |
ここでは、Java 2 SDK のツールと JDK 1.1.x ソフトウェアに付属しているツールの動作を比較して、変更点の概要について説明します。ここで説明する変更点は、Java 2 SDK のバージョン 1.2 と 1.3 の間の変更ではありません。
CLASSPATH および -classpath の変更
-Xbootclasspath、-bootclasspath
oldjava
CLASSPATH を使わなくなった appletviewer
-sourcepath
ここでは、JDK1.1 と Java 2 SDK ツールのコマンド行オプションの相違点のうち、いくつか重要な点について説明します。JDK1.1 ツールのコマンド行オプションをすでに理解しているユーザを対象としています。
Java 2 SDK ツールのオプションでは、できる限り JDK 1.1 のオプションに対する下位互換性を保つようにしてあります。このドキュメントの目的は、変更点、および変更理由の概略を説明することです。変更の理由を理解して、新しい機能のより効果的な利用に役立ててください。
このドキュメントでは、Java API の仕様で指定されているように、
java.lang.Stringなどの Java プラットフォームに属するクラスを指して、「Java プラットフォームクラス」という用語を使います。これらのクラスは、classes.zipまたはrt.jar内にあります。また、CLASSPATHおよび-classpathによって設定される検索パスを指して、「クラスパス」という用語を使います。
Java 2 プラットフォームでは、java.home プロパティの値は、実行環境の格納先ディレクトリになります。Java 2 SDK の場合、これは jdk1.3\jre ディレクトリです。Java 2 Runtime Environment の場合、これは最上位レベルのディレクトリで、通常 C:\Program Files\JavaSoft\JRE\1.3 です。JDK 1.1.x ソフトウェアでは、java.home プロパティの値は、インストール先ディレクトリを指していました。
CLASSPATH および -classpath の変更クラスパスにはデフォルト値があり、
-classpathまたはCLASSPATHを使って設定できます。1.1 では、クラスパスは次のように機能しました。この
- クラスパスのデフォルト - クラスパスのデフォルト値は、(1) Java プラットフォームクラスが格納されているパス (
classes.zipまたはrt.jar)、および (2) 現在作業中のディレクトリ (.) であるCLASSPATH- 環境変数CLASSPATHが設定された場合、クラスパスは、(1) デフォルトと同様にclasses.zipまたはrt.jarを含み、その他に (2) 現在作業中のディレクトリの代わりに新しく設定された値を含む[注 1 を参照]-classpath- オプション-classpath <path>が使われた場合、<path>に (1)classes.zipまたはrt.jar、および (2) アプリケーションクラスの両方を明示的に含める必要があった-classpathの動作は、ユーザがclasses.zipへのパスを入力する必要があったため、問題になる可能性がありました。C:> java -classpath C:\jdk-path\lib\classes.zip;\app\classes Application問題になる可能性とは、この動作は本質的にエラー発生の可能性を含んでいるということです。 つまり、ユーザの責任において、同じバージョンの JDK のjavaコマンドとclasses.zipを使う必要がありました。開発チームでも、1.1.4 のjavaで 1.1.3 のclasses.zipを実行する箇所の問題のデバッグに努めましたが、ネイティブメソッドが一致しないため不可能でした。Java 2 SDK ツールによって使用される
-classpathオプションは、Java 2 SDK のCLASSPATH環境変数と同じ意味を持つので、Java プラットフォームクラスへのパスを入力する必要がなくなり、便利になりました。C:> java -classpath C:\app\classes Application開発者によっては、
println文を追加してクラスの動作方法がわかるようにするために、java\util\Vector.classなどの個々の Java プラットフォームクラスを一時的に修正したい場合があります。Java 2 SDK では、1.1 とは異なり-classpathオプションを使って Java プラットフォームクラスへのパスを設定することはできません。このような場合、Java 2 SDK では-Xbootclasspathオプションを使う必要があります。注 1 - 上記の箇条書きに反して、
CLASSPATH環境変数にclasses.zipへのパスを明示的に指定しているユーザもいますが、これはまったく必要ありません。
前のセクションでは、JDK 1.1 にはクラスの検索に使う検索パスが 1 つあり、その値は
-classpathオプション、またはCLASSPATH環境変数によって設定できることを示しました。Java 2 SDK では、クラスの検索に使う検索パスは 3 つあります。
javaが最初にクラスを検索する場所は、ブートストラップクラスパスです。このパスの値は、System.getProperty("sun.boot.class.path")を呼び出して調べることができます。なお、接頭辞sun.は、少なくとも現在のところは、このプロパティが Sun の実装特有のものであることを示します。javaが次にクラスを検索する場所は、拡張機能ディレクトリです。ディレクトリの一覧は、System.getProperty("java.ext.dirs")を呼び出して調べることができます。javaが 3 番目にクラスを検索する場所は、アプリケーションクラスパスです。このパスの値は、System.getProperty("java.class.path")を呼び出して調べることができます。項目 2 の新しい「拡張機能ディレクトリ」機能については、javac の説明および 「Java 拡張機能機構」を参照してください。
Java 2 SDK ツールでは、
-classpathオプションとともに指定する引数は、「アプリケーションクラスパス」の値で、アプリケーションを構成するクラスのパスを含んでいる必要があります。「ブートストラップクラスパス」は、rt.jarというファイルに含まれた Java プラットフォームクラスへのパスを含みます。これについては、次のセクションで説明します。
-Xbootclasspath、-bootclasspath注 - オプションの先頭の「X」の意味については、「標準オプションと非標準オプション」を参照してください。-Xbootclasspath- すでに説明したとおり、「ブートストラップクラスパス」は、rt.jarに含まれた Java プラットフォームクラスへのパスを含みます。Java プラットフォームクラスが見つかった位置をオーバーライドする必要がある場合は、-Xbootclasspathオプションを使わなければなりません。 これは、-classpathがこの機能を提供していた 1.1 からの大きな変更点です。次に例を示します。C:> java -Xbootclasspath:C:\my\bootclasses;C:\jre\lib\rt.jar MyApplicationこの例では、
javaコマンドで-Xbootclasspathによって提供されたパスを探し、Java プラットフォームクラスを見つけます。rt.jar内を検索する前に、まず、C:\my\bootclassesディレクトリを検索します。java\util\Vector.classにデバッグ文を追加する場合は、修正したクラスファイルをC:\my\bootclassesの下に置きます。この修正版のファイルが最初に見つけられ、検索が終了し、修正版がロードされます。
-bootclasspath- さらに、javacは、コンパイルを行うプラットフォームクラスの変更に使用できる同様のオプション-bootclasspathをサポートしています。このオプションは、バグが修正された Java 2 SDK の javac を利用して 1.1 のアプリケーションをコンパイルするときにもっとも便利です。詳しい方法については、このオプションの説明を参照してください。以下は、両方のオプションに関連した注意事項です。
- Java プラットフォームクラスのオーバーライドを避ける - Java 2 Runtime Environment 再配布ライセンスでは、
rt.jarの一部を置き換えることは許可されていません。アプリケーションとともに Runtime Environment を再配布する際は、-Xbootclasspathオプションを使ってrt.jarの一部をオーバーライドすることはできません。再配布時にブートクラスパス上にアプリケーションを置く必要がある場合は、oldjavaコマンドを使うことをお勧めします。oldjavaを使わない場合は、変更されていないrt.jarおよびi18n.jar(省略可能) を、-Xbootclasspath 内のアプリケーションクラスより前の位置に記述する必要があります。例を示します。# If app needs to be deployed on -Xbootclasspath, then use: C:> java -Xbootclasspath:C:\jre\lib\rt.jar;C:\app\classes Application # instead of accidentally overriding rt.jar: C:> java -Xbootclasspath:C:\app\classes;C:\jre\lib\rt.jar Application- クラスパス検索の実装 - これらのパスが
javaの実装によってどのように結び付けられるかについて簡単に説明します。Java 2 プラットフォームでは、「親」クラスローダの概念を導入しています。Java 2 プラットフォームでは、正常に動作するクラスローダは、クラスローダ自体の機構 (検索するよう要求されたパスなど) を使ってクラスを検索する前に、その親がそのクラスをロードできるかどうかをチェックします。
Java Runtime には、次の 3 つのクラスローダがあります。 親クラスローダは、子の上に示されています。
bootstrap classloader | extension classloader | application classloaderブートストラップクラスローダは、ブートストラップクラスパス上でだけクラスを検索し、ほかのパス上では検索しません。同様に、拡張機能クラスローダは、拡張機能ディレクトリからロードされた拡張機能で検索を行い、アプリケーションクラスローダは、アプリケーションクラスパス上でだけ検索を行います。たとえば、次のコマンドを使ってアプリケーションを起動するとします。
C:> java -classpath C:\my\classes MyApplicationこのコマンドにより、一連のステップが発生し、それぞれのクラスローダに順にアプリケーションクラスをロードする機会が与えられます。最初に、このjavaコマンドは、アプリケーションクラスローダ (-classpath値を使うクラスローダ) にMyApplicationをロードするように問い合わせます。しかし、アプリケーションクラスローダは、このクラスをロードする代わりに、親の拡張機能クラスローダに、このクラスをロードするように問い合わせます。拡張機能クラスローダも同様に、その親であるブートストラップクラスローダにこのクラスをロードするように問い合わせます。 ブートストラップクラスローダは、Virtual Machine 内に構築されており、親はありません。そこでブートストラップクラスローダがブートストラップクラスパスからこのクラスをロードしようとします。 しかし、MyApplicationを見つけられないので (-Xbootclasspathを使わずデフォルトパスのままにしたため)、ブートストラップクラスローダは拡張機能クラスローダにクラスのロードを許可しますが、拡張機能クラスローダもこのクラスを見つけることができません (-Djava.ext.dirsを使わずデフォルトパスのままにしたため)。最終的に、アプリケーションクラスローダがC\my\classes\MyApplication.classを見つけ、ロードします。クラスの検索が「最初にブートストラップ、次に拡張機能、最後にアプリケーション」という順番で行われるのは、このような親子関係があるためです。詳細は、「Java 拡張機能機構」を参照してください。
oldjavaoldjava
CLASSPATH を使わなくなった appletviewer
appletviewerは 1.1 ではCLASSPATH環境設定を無視しませんでしたが、Java 2 SDK では無視します。これは、思い切った変更のようですが、アプレットのテスト時には必要なセマンティクスです。JDK 1.1 では動作し、Java 2 SDK では動作しなくなった例を考えてみます。.html ファイルを
.classファイルとは別の場所に置いたとします。JDK 1.1 では、CLASSPATHを.classファイルに設定でき、appletviewerはそれを認識しました。# Foo.class and foo.html are in different directories. C:> dir \home\user\htmls \home\user\classes C:\home\user\classes: Foo.class C:\home\user\htmls: foo.html # Foo.class is NOT in applet's codebase: C:> type \home\user\htmls\foo.html <applet code=Foo height=100 width=100></applet> # Can an applet use a class outside its codebase? C:> set CLASSPATH=C:\home\user\classes # Works in 1.1. C:> appletviewer \home\user\htmls\foo.html # ClassNotFoundException with the Java 2 SDK! C:> appletviewer \home\user\htmls\foo.htmlこのような正常に見える動作を変更したのは、 JDK
appletviewerとは異なり、CLASSPATHが優先されないブラウザでアプレットが実行された場合、Java 2 SDK を使った場合と同じ問題が発生するためです。アプレットによって参照されるクラスは、次のどちらかである必要があります。アプレットのユーザが
- ブラウザ内に存在する
java.lang.Stringなどの Java プラットフォームクラス- アプレットの
codebaseからダウンロード可能なクラスCLASSPATHを設定することを前提にはできません。 たとえ、ユーザがCLASSPATHを設定したとしても、ブラウザによって無視される可能性もあります。このため、1.2 では、appletviewerはブラウザと同じことを行います。
CLASSPATHを優先する 1.1 のappletviewerには長所もありました。 たとえば、電子メール関連の機能を提供するmailx.jarなどのサードパーティのライブラリを取得してCLASSPATH上に配置すると、アプレットでmailx.jar内のクラスを参照できたことです。Java 2 SDK で同じ便宜性を保つためには、Java 拡張機能機構の使用をお勧めします。(拡張機能機構は、「開発」時だけのソリューションであるCLASSPATHとは異なり、配置用のソリューションです。
Java 2 SDK ツールでは、
-Xという接頭辞が付いているオプションと付いていないオプションがあります。1.1 では、Virtual Machine の起動ヒープサイズを 10M バイトに設定する必要があった場合、次のように指定しました。C:> java -ms10m ApplicationJava 2 SDK では、
-Xを付けて同じオプションを表現します。C:> java -Xms10m Applicationこの目的は、Java 2 SDK ツールでは、すべての Virtual Machine に適用できるオプションと、特定の Virtual Machine の実装に特有のオプションとを区別することです。すべての Virtual Machine でクラスパスの設定が可能であることを前提としていますが、すべての Virtual Machine で初期ヒープサイズをサポートすることは前提にしていません。
コンパイラおよび Virtual Machine のベンダーが同じ標準オプションをサポートするようになり、最終的には、コンパイラを交換しても Makefile を変更する必要がなくなり、スクリプトを使って起動するサーバアプリケーション用の Virtual Machine を交換してもスクリプトを修正する必要がなくなります。
下位互換性維持のために、Java 2 SDK の
java起動ツールは、内部で-ms10mを-Xms10mに変換するので、古い-ms10mオプションを使うこともできますが、新しい構文を使うことをお勧めします。現時点の標準オプションの一覧を表示するには、次のように入力します。
C:> java -help C:> javac -help現時点の非標準オプションの一覧を表示するには、次のように入力します。
C:> java -X C:> javac -Xベンダーの方々へ -- この標準と非標準のコマンド行オプションの区分は、規格適合要件とは別の問題です。前述したように、将来的に標準オプションがオプションの事実上の規格になった場合に、ユーザの作業が楽になるようにするためのものです。
-sourcepath 1.1 では、javacおよびjavadocは、ソースファイルとクラスファイルのどちらも、CLASSPATH環境変数に指定されたパス内で検索していました。たとえば、foo\bar\FooBar.javaをコンパイルし、クラスFooBarがHelperクラスに依存しているとします。 javac は、CLASSPATH 内でソースファイルHelper.javaの検索を試みます。C:> dir \tmp\foo\bar\*.java \tmp\foo\bar\FooBar.java \tmp\foo\bar\Helper.java # Error because javac can't find Helper.class or Helper.java C:> javac \tmp\foo\bar\FooBar.java \tmp\foo\bar\FooBar.java:3: Superclass foo.bar.Helper of ... not found. C:> set CLASSPATH=\tmp # Works because javac snooped in CLASSPATH for source files C:> javac \tmp\foo\bar\FooBar.javaJava 2 SDK でも、-sourcepath <path>オプションを含めないと、これらのツールはCLASSPATH内でソースファイルを検索します。-sourcepath <path>オプションを含める場合、ソースファイルは<path>内でだけ検索され、CLASSPATH内では検索されません。C:> set CLASSPATH=\tmp # This still works with the Java 2 SDK: C:> javac \tmp\foo\bar\FooBar.java # But it doesn't work if you use -sourcepath C:> javac -sourcepath . \tmp\foo\bar\FooBar.java \tmp\foo\bar\FooBar.java:3: Superclass foo.bar.Helper ... not found.