web-dev-qa-db-ja.com

CLASSPATHとJava.ext.dirs

(おそらく非常に長い)CLASSPATH変数を使用して、クラスパスdurignアプリケーションで実行する必要があるjarを設定してから、Java 1.5+ property -Djava.ext.dirsは、検索するjarのディレクトリ全体を指定しますか?

実際の例にするために、スタンドアロンのJava libフォルダを含むアプリケーションにすべての依存jarが含まれています。これまでのところ、開始スクリプトはすべての(多分20)jarをCLASSPATH変数に設定しています1つずつ。現在、私のアプリケーションアーカイブはMavenによって生成されているので、事前にjar名が何であるかを確認できません(たとえば、JARのバージョンを変更します)。もちろん、lib dir起動スクリプトで、そこにあるすべてのjarをCLASSPATH変数に再度追加します。または、おそらくmavenにこのスクリプトを生成させます。

1)Java.ext.dirsプロパティを設定して、スクリプトに追加のlib dirを含めるだけで、これをすべて置き換えても問題ありませんか?そこに隠された警告はありますか?

返信ありがとうございます:)

20
Jan Zyka

Java.ext.dirsには非常に特殊な用途があります。これは 拡張メカニズム がクラスをロードする場所を指定するために使用されます。 JREまたは他のライブラリ(JAIなど)に機能を追加するために使用されます。これは、汎用のクラスロードメカニズムを意味するものではありません。

ワイルドカード文字* 代わりに。これはJava 6で導入されたので、それが可能かどうかまだ多くの人が知らない。

34
Joachim Sauer

ヨアヒムは、ワイルドカード文字のショートカットについて良い指摘をしました。しかし、質問は違いと注意点について尋ねているので...

1つの違いは、-Djava.ext.dirsフラグの下でライブラリを指定すると、拡張クラスローダーを使用して読み込まれる(例 Sun.misc.Launcher.ExtClassLoader )システムクラスローダーの代わり(例 Sun.misc.Launcher.AppClassLoader ).

ライブラリに、Libという名前のクラスがあると仮定します。そして、私たちのアプリケーションはこのコードを実行します:

public class Main {
    public static void main(String args[]) {
        System.out.println(System.getProperty("Java.ext.dirs"));
        ClassLoader test_cl = Main.class.getClassLoader();
        ClassLoader lib_cl = Lib.class.getClassLoader();
        System.out.println(test_cl == lib_cl);
        System.out.println(test_cl);
        System.out.println(lib_cl);
    }
}

コンソール出力は次のようになります。

C:\Program Files\Java\jdk1.6.0\jre\lib\ext;C:\WINDOWS\Sun\Java\lib\ext
true
Sun.misc.Launcher$AppClassLoader@107077e
Sun.misc.Launcher$AppClassLoader@107077e

コマンドJava -cp "folder/*;." Mainを使用してアプリケーションを実行したとき。

ただし、アプリケーションがコマンドJava -Djava.ext.dirs=folder Mainを使用して実行された場合、出力は次のようになります。

folder
false
Sun.misc.Launcher$AppClassLoader@107077e
Sun.misc.Launcher$ExtClassLoader@7ced01
5
Pacerier

Lib.extディレクトリに物を置くことの大きな問題は、アプリケーションごとに異なるバージョンのライブラリが必要になる可能性があり、それらは互いに競合する可能性があることです。

ほとんどのソフトウェア開発者がWindows/Systemディレクトリに共有ライブラリを配置したために多くの場合に同様の状況が発生したとき、古いDLL地獄からWindows 3日間の地獄(あなたがそれらを覚えている場合)を考えてください)それらをアプリケーションに含めて明示的にロードするのではなく、そこから自動的に再選択されます。

代わりに、アプリケーションごとに個別のクラスパス(システムレベルのクラスパスはありません!)を設定し、起動スクリプトに設定して、その特定のアプリケーションに適用可能なjarファイルとクラスディレクトリのみを指すようにします。このようにして、ライブラリのニーズが競合する複数のアプリケーションを、他の機能を妨げることなく並べて起動できます。

アプリケーションのテスト中に外部ライブラリがアプリケーションに干渉することを望まない開発者の場合も同様です。そして、もう1つあります。lib/ extトリック(またはシステムレベルのクラスパス)を開発して使用している場合、出荷するアプリケーションが正しいライブラリに同梱されていることをどのようにして確認できるでしょうか。をインストーラーまたはインストールパッケージに含めるのを忘れた場合、共有場所にあるマシン上にあるため、気付かないでしょう。しかし、そのライブラリを持たない顧客は、ランタイムエラーを受け取り、まもなく電話でサポートを要求します(そして、場合によっては払い戻し、そして不良品を出荷するためにプレスで悪いレビューを与えます)。

4
jwenting