2

重複の可能性:
実行時の CLASSPATH の設定

重複の可能性:実行時に CLASSPATH を設定する

私が使用しているクラスパスを取得するには:

 ClassLoader cl = ClassLoader.getSystemClassLoader();
     URL[] urls = ((URLClassLoader)cl).getURLs();
     for(URL url: urls){
         System.out.println("classpath:"+url.getFile());
         }

実行時にクラスパスにjarをロードするコードを手伝ってくれる人がいますか。

ClassLoader currentThreadClassLoader
     = Thread.currentThread().getContextClassLoader();
    URLClassLoader urlClassLoader
     = new URLClassLoader(new URL[]{new File("D:\\ms.jar").toURL()},
                          currentThreadClassLoader);
    Thread.currentThread().setContextClassLoader(urlClassLoader);

これはうまくいかないようです。

4

2 に答える 2

1

完全な (コード化された) ソリューションは、1 つのスタック オーバーフローの回答を少し超えるものになるため、独自の ClassLoader を作成することにした場合に、代わりに注意する必要がある点を概説します。

  1. クラスローダは名前空間 (の一部) を表し、異なるクラスローダによってロードされた 2 つの同一のクラスは「等しく」ありません。つまり、クラスローディングにはいくつかの危険が潜んでいます。特に、シングルトンが突然シングルではなくなったり、キャストが予期せず失敗したりします。
  2. クラスローダーは、自分自身で何かを試みる前に、「親」ローダーに委譲するパターンで動作する必要があります (上記を参照)。
  3. クラスのロードとリンクは 2 つの別個のステップです (ブログの投稿やオンラインの Java 記事に見られるようなクラスローダーの実装例では、簡単にするために 2 つを 1 つにまとめています)。すべての依存関係もロードしたクラス...
  4. これはすべて、ローダー A によってロードされたクラス A が、ローダー A もその親のいずれもロードできないクラス B を参照する場合に問題があることを意味します。完全に解決 (リンク) できません。
  5. また、クラスローダが同期された方法でクラスをロードすることを確認する必要があります。そうしないと、ステップ 1 で示唆された問題が、クラスローダによる重複から、同じクラスローダを使用する複数のスレッドからの重複へと飛躍する可能性があります...

注:プログラムのラッパースクリプト/バッチファイルでスイッチを使用する方がはるかに簡単です。-cp

于 2012-10-18T21:11:18.390 に答える
0

ClassLoader#getSystemClassLoader()ドキュメントから:

このメソッドは、ランタイムの起動シーケンスの早い段階で最初に呼び出され、その時点でシステムクラスローダーを作成し、呼び出し元のスレッドのコンテキストクラスローダーとして設定します。

を行うThread.currentThread().setContextClassLoader(urlClassLoader)と、現在のスレッドの参照ではなく、現在のスレッドの参照を変更することにClassLoader なります(これを変更することはできません)。したがって、それ以降は、現在のスレッドの新しいクラスローダーを使用してクラスをロードする必要があります。次のようなもので:

Thread.currentThread().getContextClassLoader().loadClass(...) 
于 2012-10-18T21:12:10.247 に答える