webentwicklung-frage-antwort-db.com.de

Wie lade ich Klassen zur Laufzeit aus einem Ordner oder einer JAR?

Ich versuche, ein Java Tool zu erstellen, das die Struktur einer Java Anwendung durchsucht und einige aussagekräftige Informationen liefert. Dazu muss ich in der Lage sein Es erweist sich als nahezu unmöglich, alle .class-Dateien vom Projektspeicherort (JAR/WAR oder nur einem Ordner) aus zu scannen und mithilfe von Reflection Informationen über ihre Methoden zu erhalten.

Ich kann viele Lösungen finden, die auf URLClassloader basieren und es mir ermöglichen, bestimmte Klassen aus einem Verzeichnis/Archiv zu laden, aber keine, mit denen ich Klassen laden kann, ohne Informationen über den Klassennamen oder die Paketstruktur zu haben.

EDIT: Ich denke, ich habe das schlecht formuliert. Mein Problem ist nicht, dass ich nicht alle Klassendateien bekommen kann, ich kann das mit Rekursion usw. machen und sie richtig lokalisieren. Mein Problem besteht darin, ein Klassenobjekt für jede Klassendatei zu erhalten.

57
Sam Stern

Der folgende Code lädt alle Klassen aus einer JAR-Datei. Es muss nichts über die Klassen wissen. Die Namen der Klassen werden aus dem JarEntry extrahiert.

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);

}

bearbeiten:

Wie in den obigen Kommentaren vorgeschlagen, wäre auch Javassist eine Möglichkeit. Initialisieren Sie einen ClassPool irgendwo vor der while-Schleife aus dem obigen Code, und anstatt die Klasse mit dem Klassenladeprogramm zu laden, können Sie ein CtClass-Objekt erstellen:

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

In der ctClass können Sie alle Methoden, Felder, verschachtelten Klassen usw. abrufen. Sehen Sie sich die Javassist-API an: https://jboss-javassist.github.io/javassist/html/index.html)

99
Apfelsaft

Listet alle Klassen in der JAR-Datei auf.

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;
}
9
amicngh

Dazu muss ich in der Lage sein, alle .class-Dateien vom Projektspeicherort aus (JAR/WAR oder nur ein Ordner) zu scannen.

Das Scannen aller Dateien in einem Ordner ist einfach. Eine Möglichkeit besteht darin, File.listFiles() für das File aufzurufen, das den Ordner angibt, und dann das resultierende Array zu iterieren. Verwenden Sie die Rekursion, um die Strukturen verschachtelter Ordner zu durchlaufen.

Das Durchsuchen der Dateien einer JAR-Datei kann mit der JarFile-API durchgeführt werden. Sie müssen nicht erneut den Vorgang ausführen, um verschachtelte "Ordner" zu durchlaufen.

Beides ist nicht besonders kompliziert. Lesen Sie einfach das Javadoc und starten Sie die Codierung.

6
Stephen C