0

システムクラスローダーを使用して他のいくつかのクラスをロードする別のクラスのラッパーとしてantタスクを実装しています。現在、タスクはこれらの他のクラスの同じjarファイルにあるため、タスクが実行されているため、なぜそれらが見つからないのだろうか

$CLASSPATH私のクラスはenv変数にあることに注意してください。問題は発生しませんexport LOCALCLASSPATH=$CLASSPATH

最小限の例:

<taskdef name="mytask" classname="my.package.MyTask"  />

<target name="compile">
    <mytask />
</target>

ここで問題を簡単に確認できます

public class MyTask extends Task {
   public void execute() throws BuildException {
    try {
        ClassLoader cl = ClassLoader.getSystemClassLoader();

        // this will only print the ant jar file path
        for(URL url: ((URLClassLoader)cl).getURLs()){
        log(url.getFile());
        }

        cl.loadClass("my.package.OtherClass"); // throws an exception

    } catch (Exception ex) {
        throw new BuildException(ex);
    }
  }

}
4

1 に答える 1

0

シェルantスクリプトは内部的にクラスパスを作り直すため、SystemClassLoader には「実際の」クラスパスの最小限の部分のみが含まれます。

tl;dr: 使用

    ClassLoader cl = Thread.currentThread().getContextClassLoader();

それ以外の

    ClassLoader cl = ClassLoader.getSystemClassLoader();

メーリング リストから、Rainer Noack :

シェル スクリプト経由で ant を起動している場合は、oata.launcher.Launcher.java を使用しています。

このクラスは、クラスパスを少し再編成します。環境変数 CLASSPATH と classpath コマンドライン引数は削除され、ant の起動に使用される最小のクラスパスに置き換えられます。システム クラスローダの子クラスローダは、元の CLASSPATH エントリで作成されます。次に、oata.Project がこのクラスローダーでロードされます。

問題は、 のローダーClassLoader.getSystemClassLoader()が実際には変更されておらず、変更されたもの (つまり、$CLASSPATH、-lib などを尊重するもの) を を使用して取得できることThread.currentThread().getContextClassLoader()です。

于 2013-03-27T09:16:16.587 に答える