73

Java アプリケーションの構造をスキャンし、意味のある情報を提供する Java ツールを作成しようとしています。これを行うには、プロジェクトの場所 (JAR/WAR またはフォルダーのみ) からすべての .class ファイルをスキャンし、リフレクションを使用してそれらのメソッドを読み取ることができる必要があります。これはほぼ不可能であることが証明されています。

URLClassloader に基づいて、ディレクトリ/アーカイブから特定のクラスをロードできる多くのソリューションを見つけることができますが、クラス名やパッケージ構造に関する情報がなくてもクラスをロードできるソリューションはありません。

編集:これは言い方が悪いと思います。私の問題は、すべてのクラス ファイルを取得できないことではありません。再帰などを使用して適切に検索できます。私の問題は、各クラス ファイルの Class オブジェクトを取得することです。

4

4 に答える 4

119

次のコードは、JAR ファイルからすべてのクラスをロードします。クラスについて何も知る必要はありません。クラスの名前は JarEntry から抽出されます。

JarFile jarFile = new JarFile(pathToJar);
Enumeration<JarEntry> e = jarFile.entries();

URL[] urls = { new URL("jar:file:" + pathToJar+"!/") };
URLClassLoader cl = URLClassLoader.newInstance(urls);

while (e.hasMoreElements()) {
    JarEntry je = e.nextElement();
    if(je.isDirectory() || !je.getName().endsWith(".class")){
        continue;
    }
    // -6 because of .class
    String className = je.getName().substring(0,je.getName().length()-6);
    className = className.replace('/', '.');
    Class c = cl.loadClass(className);

}

編集:

上記のコメントで示唆されているように、javassist も可能性があります。上記のコードの while ループの前のどこかで ClassPool を初期化し、クラス ローダーでクラスをロードする代わりに、CtClass オブジェクトを作成できます。

ClassPool cp = ClassPool.getDefault();
...
CtClass ctClass = cp.get(className);

ctClass から、すべてのメソッド、フィールド、ネストされたクラスなどを取得できます。javassist API をご覧ください: https://jboss-javassist.github.io/javassist/html/index.html

于 2012-06-13T13:54:13.350 に答える
11

jar ファイル内のすべてのクラスを一覧表示します。

public static List getClasseNames(String jarName) {
    ArrayList classes = new ArrayList();

    if (debug)
        System.out.println("Jar " + jarName );
    try {
        JarInputStream jarFile = new JarInputStream(new FileInputStream(
                jarName));
        JarEntry jarEntry;

        while (true) {
            jarEntry = jarFile.getNextJarEntry();
            if (jarEntry == null) {
                break;
            }
            if (jarEntry.getName().endsWith(".class")) {
                if (debug)
                    System.out.println("Found "
                            + jarEntry.getName().replaceAll("/", "\\."));
                classes.add(jarEntry.getName().replaceAll("/", "\\."));
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return classes;
}
于 2012-06-13T14:03:30.180 に答える
6

これを行うには、プロジェクトの場所 (JAR/WAR またはフォルダーのみ) からすべての .class ファイルをスキャンできる必要があります。

フォルダ内のすべてのファイルをスキャンするのは簡単です。1 つのオプションは、フォルダーを示すを呼び出しFile.listFiles()てから、結果の配列を反復処理することです。Fileネストされたフォルダーのツリーをトラバースするには、再帰を使用します。

JAR ファイルのファイルのスキャンは、JarFileAPI を使用して行うことができます ... ネストされた「フォルダー」をトラバースするために再帰する必要はありません。

これらはどちらも特に複雑ではありません。javadoc を読んで、コーディングを開始してください。

于 2012-06-13T13:54:18.860 に答える