Wie bekomme ich Namen von Klassen in einer JAR-Datei?

112

Ich habe eine JAR-Datei und muss den Namen aller Klassen in dieser JAR-Datei abrufen. Wie kann ich das machen?

Ich habe es gegoogelt und etwas über JarFile oder Java gesehen, ClassLoaderaber ich habe keine Ahnung, wie es geht.

Sticksu
quelle
Verwenden Sie eine IDE, da diese automatisch angezeigt wird, wenn Sie eine verwenden.
Joey Rohan
Ich verwende Eclipse, muss dies jedoch mit Code tun.
Sticksu
@LuiggiMendoza - Das potenzielle Duplikat enthält Antworten mit Beispielen sowie Ressourcen für die Dokumentation. Wenn Sie nach einem dieser Klassennamen + Beispiel suchen, erhalten Sie mehrere nützliche Ergebnisse.
Aiias
@Alias ​​das mögliche Duplikat gibt an, wie eine Datei aus einem JAR gefunden und abgerufen werden kann, während die Frage darin besteht, die Klassennamen in einem JAR abzurufen (möglicherweise die Klassen in allen darin enthaltenen Paketen). Der Link in ErikKajus Antwort weist auf eine mögliche Lösung mit JarInputStreamund JarEntryKlassen hin, die ich in keiner Antwort auf Ihren verwiesenen Link finden kann.
Luiggi Mendoza

Antworten:

68

Leider bietet Java keine einfache Möglichkeit, Klassen in der "nativen" JRE aufzulisten. Damit haben Sie einige Möglichkeiten: (a) Für jede gegebene JAR-Datei können Sie die Einträge in dieser JAR-Datei auflisten, die .classDateien suchen und dann bestimmen, welche Java-Klasse jede .classDatei darstellt; oder (b) Sie können eine Bibliothek verwenden, die dies für Sie erledigt.

Option (a): Manuelles Scannen von JAR-Dateien

In dieser Option füllen wir classNamesdie Liste aller Java-Klassen aus, die in einer JAR-Datei unter enthalten sind /path/to/jar/file.jar.

List<String> classNames = new ArrayList<String>();
ZipInputStream zip = new ZipInputStream(new FileInputStream("/path/to/jar/file.jar"));
for (ZipEntry entry = zip.getNextEntry(); entry != null; entry = zip.getNextEntry()) {
    if (!entry.isDirectory() && entry.getName().endsWith(".class")) {
        // This ZipEntry represents a class. Now, what class does it represent?
        String className = entry.getName().replace('/', '.'); // including ".class"
        classNames.add(className.substring(0, className.length() - ".class".length()));
    }
}

Option (b): Verwendung spezialisierter Reflexionsbibliotheken

Guave

Guave hat ClassPathseit mindestens 14.0, die ich benutzt und gemocht habe. Das Schöne daran ClassPathist, dass die gefundenen Klassen nicht geladen werden. Dies ist wichtig, wenn Sie nach einer großen Anzahl von Klassen suchen.

ClassPath cp=ClassPath.from(Thread.currentThread().getContextClassLoader());
for(ClassPath.ClassInfo info : cp.getTopLevelClassesRecurusive("my.package.name")) {
    // Do stuff with classes here...
}

Reflexionen

Ich habe die Reflections-Bibliothek nicht persönlich benutzt , aber sie scheint sehr beliebt zu sein. Auf der Website finden Sie einige gute Beispiele wie diese schnelle Möglichkeit, alle Klassen in ein Paket zu laden, das von einer JAR-Datei bereitgestellt wird. Dies kann auch für Ihre Anwendung nützlich sein.

Reflections reflections = new Reflections("my.project.prefix");

Set<Class<? extends SomeType>> subTypes = reflections.getSubTypesOf(SomeType.class);

Set<Class<?>> annotated = reflections.getTypesAnnotatedWith(SomeAnnotation.class);
sigpwned
quelle
Reflexionen funktionieren auch nicht, wenn sie von einem ausführbaren JAR ausgeführt werden.
Luke
Eine Spring-Lösung, die mit ausführbaren Jars arbeitet: stackoverflow.com/a/21430849/4265610 .
Luke
1
Benutz einfach. jar tvf jarfile.jar. Warum machst du das alles für.
Philip Rego
183

Sie können das Java- jarTool verwenden. Listen Sie den Inhalt der JAR-Datei in einer TXT-Datei auf, und Sie können alle Klassen im JAR sehen.

jar tvf jarfile.jar

-t Inhaltsverzeichnis für Archiv auflisten

-v erzeugt eine ausführliche Ausgabe auf der Standardausgabe

-f Name der Archivdatei angeben

Sanjeev Gupta
quelle
1
Vielen Dank. Dies beantwortet den Teil "Nur eine Klassenliste erhalten" des OP, der nicht gefragt wurde.
Octopusgrabbus
9
Sie können auch zur Not verwenden unzip -l jarfile.jar. Eine JAR-Datei ist nur eine Zip-Datei mit einem Manifest!
Sigpwned
3
Das Problem ist, dass er wahrscheinlich die Klassendateien zur Laufzeit in einem JAR abrufen wollte, wenn eine Classloader-Instanz vorliegt (wahrscheinlich, um zu sehen, welche Klassen in diesem bestimmten JAR geladen werden).
Richard Duerr
19

Vielleicht suchen Sie nach einem jarBefehl, um die Liste der Klassen im Terminal abzurufen.

$ jar tf ~/.m2/repository/org/apache/spark/spark-assembly/1.2.0-SNAPSHOT/spark-assembly-1.2.0-SNAPSHOT-hadoop1.0.4.jar 
META-INF/
META-INF/MANIFEST.MF
org/
org/apache/
org/apache/spark/
org/apache/spark/unused/
org/apache/spark/unused/UnusedStubClass.class
META-INF/maven/
META-INF/maven/org.spark-project.spark/
META-INF/maven/org.spark-project.spark/unused/
META-INF/maven/org.spark-project.spark/unused/pom.xml
META-INF/maven/org.spark-project.spark/unused/pom.properties
META-INF/NOTICE

wo,

-t  list table of contents for archive
-f  specify archive file name

Oder grep einfach über das Ergebnis, um .classes nur zu sehen

$ jar tf ~/.m2/repository/org/apache/spark/spark-assembly/1.2.0-SNAPSHOT/spark-assembly-1.2.0-SNAPSHOT-hadoop1.0.4.jar | grep .class
org/apache/spark/unused/UnusedStubClass.class

Um die Anzahl der classes zu sehen,

jar tvf launcher/target/usergrid-launcher-1.0-SNAPSHOT.jar | grep .class | wc -l
61079
betenagupd
quelle
2
Dies war genau das, was ich brauchte, auch wenn der Fragenbesitzer eine codebasierte Lösung benötigte. Vielen Dank!
Providencemac
10

Dies ist ein Hack, den ich benutze:

Sie können die javaautomatische Vervollständigung folgendermaßen verwenden:

java -cp path_to.jar <Tab>

Dadurch erhalten Sie eine Liste der Klassen, die als Startklasse übergeben werden können. Der Versuch, eine zu verwenden, die keine Hauptdatei enthält, führt natürlich zu nichts, aber Sie können sehen, wie javadie Klassen in der Klasse .jarheißen.

stanm
quelle
7

Du kannst den ... benutzen

jar tf example.jar
loneStar
quelle
5

Du kannst es versuchen:

jar tvf jarfile.jar 

Dies ist nur hilfreich, wenn Ihr JAR ausführbar ist, dh im Manifest haben Sie eine Klasse als Hauptklasse definiert

Pallav
quelle
Fügen Sie Ihrer Antwort ein bestimmtes Beispiel für ein Beispielglas hinzu.
Juru
4

Der folgende Befehl listet den Inhalt einer JAR- Datei auf.

Befehl: - unzip -l jarfilename.jar.

Probe o / p: -

Archive: hello-world.jar Length Date Time Name --------- ---------- ----- ---- 43161 10-18-2017 15:44 hello-world/com/ami/so/search/So.class 20531 10-18-2017 15:44 hello-world/com/ami/so/util/SoUtil.class --------- ------- 63692 2 files

Laut Handbuch von unzip

-l listet Archivdateien auf (Kurzformat). Die Namen, unkomprimierten Dateigrößen sowie Änderungsdaten und -zeiten der angegebenen Dateien werden zusammen mit den Summen für alle angegebenen Dateien gedruckt. Wenn UnZip mit definiertem OS2_EAS kompiliert wurde, listet die Option -l auch Spalten für die Größe der gespeicherten erweiterten OS / 2-Attribute (EAs) und OS / 2-Zugriffssteuerungslisten (ACLs) auf. Außerdem werden der Zipfile-Kommentar und einzelne Dateikommentare (falls vorhanden) angezeigt. Wenn eine Datei aus einem Einzelfall-Dateisystem (z. B. dem alten MS-DOS-FAT-Dateisystem) archiviert wurde und die Option -L angegeben wurde, wird der Dateiname in Kleinbuchstaben konvertiert und mit einem Caret (^) versehen.

Opster Elasticsearch Ninja
quelle
Während dieser Code - Schnipsel zu begrüßen ist, und etwas Hilfe bieten kann, würde es erheblich verbessert , wenn es eine Erklärung enthalten von , wie und warum Dies löst das Problem. Denken Sie daran, dass Sie in Zukunft die Frage für die Leser beantworten, nicht nur für die Person, die jetzt fragt! Bitte bearbeiten Sie Ihre Antwort, um eine Erklärung hinzuzufügen, und geben Sie an, welche Einschränkungen und Annahmen gelten.
Toby Speight
2

Sie können dies versuchen:

unzip -v /your/jar.jar

Dies ist nur hilfreich, wenn Ihr JAR ausführbar ist, dh im Manifest haben Sie eine Klasse als Hauptklasse definiert

Abhimanyu Dutta
quelle
1

Verwenden Sie dieses Bash-Skript:

#!/bin/bash

for VARIABLE in *.jar
do
   jar -tf $VARIABLE |grep "\.class"|awk -v arch=$VARIABLE '{print arch ":" $4}'|sed 's/\//./g'|sed 's/\.\.//g'|sed 's/\.class//g'
done

Dadurch werden die Klassen in Gläsern in Ihrem Verzeichnis in der folgenden Form aufgelistet:

file1.jar:fullyqualifiedclassName
file1.jar:fullyqualifiedclassName
file1.jar:fullyqualifiedclassName
file1.jar:fullyqualifiedclassName
file2.jar:fullyqualifiedclassName
file2.jar:fullyqualifiedclassName
file2.jar:fullyqualifiedclassName

Beispielausgabe:

commons-io.jar:org.apache.commons.io.ByteOrderMark
commons-io.jar:org.apache.commons.io.Charsets
commons-io.jar:org.apache.commons.io.comparator.AbstractFileComparator
commons-io.jar:org.apache.commons.io.comparator.CompositeFileComparator
commons-io.jar:org.apache.commons.io.comparator.DefaultFileComparator
commons-io.jar:org.apache.commons.io.comparator.DirectoryFileComparator
commons-io.jar:org.apache.commons.io.comparator.ExtensionFileComparator
commons-io.jar:org.apache.commons.io.comparator.LastModifiedFileComparator

In Windows können Sie Powershell verwenden:

Get-ChildItem -File -Filter *.jar |
ForEach-Object{
    $filename = $_.Name
    Write-Host $filename
    $classes = jar -tf $_.Name |Select-String -Pattern '.class' -CaseSensitive -SimpleMatch
    ForEach($line in $classes) {
       write-host $filename":"(($line -replace "\.class", "") -replace "/", ".")
    }
}
ESPRIELLA_GREGORIO QUINTERO_DE
quelle
0

Beschreibung der Lösung : Eclipse IDE kann hierfür verwendet werden, indem ein Beispiel-Java-Projekt erstellt und alle Jars im Projekterstellungspfad hinzugefügt werden

SCHRITTE unten :

  1. Erstellen Sie ein Beispiel für ein Eclipse-Java-Projekt.

  2. Alle Gläser, die Sie in seinem Erstellungspfad haben

  3. STRG + UMSCHALT + T und Geben Sie den vollständigen Klassennamen ein.

  4. Die Ergebnisse werden im Fenster mit allen Gläsern mit dieser Klasse angezeigt. Siehe beigelegtes Foto . Geben Sie hier die Bildbeschreibung ein

Arokiadoss Asirvatham
quelle
0

windows cmd: Dies würde funktionieren, wenn Sie alle te jars im selben Verzeichnis haben und den folgenden Befehl ausführen

for /r %i in (*) do ( jar tvf %i | find /I "search_string")
Vikas
quelle
0

Mac OS: Am Terminal:

vim <your jar location>

after jar gets opened, press / and pass your class name and hit enter
Rajiv Singh
quelle