web-dev-qa-db-ja.com

クラスローダーによってロードされるjarファイルとその順序を見つける方法

私は他の場所でこの質問に対する明確な答えを見つけることができなかったので、ここで試してみます:

アプリケーションクラスローダーによってロードされたJAR /クラスのリストを、ロードされた正確な順序で取得する方法(プログラムまたはその他)はありますか?アプリケーションクラスローダーとは、アプリケーションサーバー(WLS、WAS、JBoss ...)にEARアプリケーションをロードするクラスローダーを意味しますが、明らかに、どのクラスローダーにも適用されます。

したがって、一般化するために、特定のクラスローダーによってロードされたJARのリストと順序を調べたいと思います。個々のクラスではなく、classloader.getPackages()を呼び出すことで簡単に見つけることができますが、このクラスローダーによってロードされたJARファイルのリストです。

42
Marina

短い答えはノーです。クラスローダーは、検索ロジックを公開する必要はありません。

ただし、クラスローダーインスタンスが RLClassLoader またはサブクラスである場合、getURLs()メソッドを介してjar /ディレクトリのリストにアクセスできます。このクラスのドキュメントに従って、これらのURLは順番に検索されます。

実際には、クラスのロード元を見つけようとしている場合は、Steveの答えがおそらくより便利です。

14
kdgregory

JVMオプション-verbose:classを使用しようとしましたか。ロードされたすべてのJARファイルとクラスを表示します。

例:

[Opened C:\Program Files\JDK160~1\jre\lib\rt.jar]
[Loaded Java.lang.Object from C:\Program Files\JDK160~1\jre\lib\rt.jar]
74
Steve

クラスの保護ドメイン(場所/証明書の組み合わせ)を確認します。例えばPDFParser.classの場合、次のようになります...

PDFParser.class.getProtectionDomain().getCodeSource().getLocation().toString()

Jreクラスまたは承認されたディレクトリからロードされた場合、これらのクラスが保護なしでロードされるため、例外がスローされます...

1
gmournos

別の方法として、このコードスニペットを使用できます。結果は、クラスローダーに関連するjarファイルと、オブジェクトのクラスローダー(ルートクラスローダーまで親を含むクラスローダーのチェーン)によってロードされるクラスファイルで構成されるファイルです。クラスローダーは星で区切られています。

Object obj = this;
ClassLoader classLoader = obj.getClass().getClassLoader();
File file = new File("classlodersClassesJars.txt");
if(file.exists()) {
    file.delete();
}
if(classLoader != null) { // to escape from system classes that are loaded by bootstrap class-loader such as String.
    do {
        try {
            Class clClass = classLoader.getClass();
            while(clClass != ClassLoader.class){
                    clClass = clClass.getSuperclass();
            }
            Java.lang.reflect.Field domainField = clClass.getDeclaredField("domains");
            Java.lang.reflect.Field classesField = clClass.getDeclaredField("classes");
            domainField.setAccessible(true);
            classesField.setAccessible(true);
            HashSet domains = (HashSet<String>) domainField.get(classLoader);
            Vector classes = (Vector) classesField.get(classLoader);
            FileOutputStream fos = new FileOutputStream("classlodersClassesJars.txt", true);
            fos.write(("\n******************** " + classLoader.toString() + "\n").getBytes());
            fos.write(Arrays.toString(classes.toArray()).getBytes());
            Object[] reverseDomains = domains.toArray();
            org.Apache.commons.lang.ArrayUtils.reverse(reverseDomains);
            fos.write(Arrays.toString(reverseDomains).getBytes());
            fos.close();
            classLoader = classLoader.getParent();
        } catch (Exception exception) {
            exception.printStackTrace();
            // TODO
        }
    } while (classLoader.getParent() != null);
}
0
MMKarami