Comment obtenir les noms des classes dans un fichier jar?


112

J'ai un fichier JAR et j'ai besoin d'obtenir le nom de toutes les classes dans ce fichier JAR. Comment puis je faire ça?

Je l'ai googlé et j'ai vu quelque chose à propos de JarFile ou Java, ClassLoadermais je ne sais pas comment le faire.


Utilisez-vous un IDE? Comme il sera automatiquement affiché si vous en utilisez un.
joey rohan

J'utilise Eclipse, mais je dois le faire avec du code.
sticksu

@LuiggiMendoza - Le doublon potentiel a des réponses avec des exemples ainsi que des ressources pour la documentation. La recherche d'un de ces noms de classe + exemple donnera plusieurs résultats utiles.
Aiias

@Alias ​​le doublon possible indique comment trouver et récupérer un fichier à partir d'un fichier jar, tandis que la question concerne l'obtention des noms de classe dans un fichier jar (éventuellement les classes de tous les packages à l'intérieur). Le lien dans la réponse d'ErikKaju indique une solution possible en utilisant JarInputStreamet des JarEntryclasses que je ne trouve dans aucune réponse de votre lien référencé.
Luiggi Mendoza

Réponses:


68

Malheureusement, Java ne fournit pas un moyen simple de lister les classes dans le JRE "natif". Cela vous laisse avec quelques options: (a) pour tout fichier JAR donné, vous pouvez lister les entrées à l'intérieur de ce fichier JAR, trouver les .classfichiers, puis déterminer quelle classe Java chaque .classfichier représente; ou (b) vous pouvez utiliser une bibliothèque qui le fait pour vous.

Option (a): analyse manuelle des fichiers JAR

Dans cette option, nous remplirons classNamesla liste de toutes les classes Java contenues dans un fichier jar à /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): Utilisation de bibliothèques de réflexions spécialisées

Goyave

Guava en a ClassPathdepuis au moins 14,0, ce que j'ai utilisé et aimé. Une bonne chose à propos de cela ClassPathest qu'il ne charge pas les classes qu'il trouve, ce qui est important lorsque vous recherchez un grand nombre de classes.

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

Réflexions

Je n'ai pas personnellement utilisé la bibliothèque Reflections , mais elle semble très appréciée. Quelques excellents exemples sont fournis sur le site Web comme ce moyen rapide de charger toutes les classes dans un package fourni par n'importe quel fichier JAR, ce qui peut également être utile pour votre application.

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

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

Set<Class<?>> annotated = reflections.getTypesAnnotatedWith(SomeAnnotation.class);

Les réflexions ne fonctionnent pas non plus si elles sont exécutées à partir d'un fichier jar exécutable.
Luke

Une solution Spring fonctionnant à partir de jars exécutables: stackoverflow.com/a/21430849/4265610 .
Luke

1
Utilisez simplement. jar tvf jarfile.jar. Pourquoi faites-vous tout cela pour.
Philip Rego

184

Vous pouvez utiliser l' jaroutil Java . Listez le contenu du fichier jar dans un fichier txt et vous pouvez voir toutes les classes dans le fichier jar.

jar tvf jarfile.jar

-t liste la table des matières pour l'archive

-v génère une sortie détaillée sur la sortie standard

-f spécifier le nom du fichier d'archive


1
Merci. Cela répond à la partie "juste obtenir une liste de classe" du PO qui n'a pas été posée.
octopusgrabbus

9
Vous pouvez également utiliser unzip -l jarfile.jarà la rigueur. Un fichier JAR est juste un fichier zip avec un manifeste!
sigpwned

3
Le problème est qu'il voulait probablement obtenir les fichiers de classe dans un fichier jar au moment de l'exécution, étant donné une instance de chargeur de classe (susceptible de voir quelles classes sont chargées dans ce fichier jar spécifique).
Richard Duerr

19

Peut-être cherchez-vous une jarcommande pour obtenir la liste des classes dans le terminal,

$ 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

où,

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

Ou, simplement grep au-dessus du résultat pour voir .classseulement es

$ 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

Pour voir le nombre d' classes,

jar tvf launcher/target/usergrid-launcher-1.0-SNAPSHOT.jar | grep .class | wc -l
61079

2
c'était exactement ce dont j'avais besoin, même si le propriétaire de la question avait besoin d'une solution basée sur le code. Merci!
providencemac

10

C'est un hack que j'utilise:

Vous pouvez utiliser javala saisie semi-automatique de comme ceci:

java -cp path_to.jar <Tab>

Cela vous donnera une liste des classes disponibles pour passer comme classe de départ. Bien sûr, essayer d'en utiliser un qui n'a pas de fichier principal ne fera rien, mais vous pouvez voir ce qui javapense que les classes à l'intérieur du .jarsont appelées.



5

Tu peux essayer:

jar tvf jarfile.jar 

Cela ne sera utile que si votre fichier jar est exécutable, c'est-à-dire que dans le manifeste, vous avez défini une classe comme classe principale


Ajoutez un exemple spécifique sur un pot d'exemple à votre réponse.
Juru

4

La commande ci-dessous répertorie le contenu d'un fichier jar .

commande: - unzip -l jarfilename.jar.

échantillon 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

Selon le manuel de unzip

-l liste les fichiers d'archive (format court). Les noms, les tailles de fichiers non compressés et les dates et heures de modification des fichiers spécifiés sont imprimés, ainsi que les totaux pour tous les fichiers spécifiés. Si UnZip a été compilé avec OS2_EAS défini, l'option -l répertorie également les colonnes pour les tailles des attributs étendus OS / 2 (EA) et des listes de contrôle d'accès OS / 2 (ACL). En outre, le commentaire de fichier zip et les commentaires de fichier individuels (le cas échéant) sont affichés. Si un fichier a été archivé à partir d'un système de fichiers à cas unique (par exemple, l'ancien système de fichiers MS-DOS FAT) et que l'option -L a été donnée, le nom de fichier est converti en minuscules et est précédé d'un signe curseur (^).


Bien que cet extrait de code soit le bienvenu et puisse fournir une aide, il serait grandement amélioré s'il incluait une explication sur la manière et la raison pour laquelle cela résout le problème. N'oubliez pas que vous répondez à la question des lecteurs à l'avenir, pas seulement à la personne qui la pose maintenant! Veuillez modifier votre réponse pour ajouter une explication et donner une indication des limites et des hypothèses applicables.
Toby Speight

2

Vous pouvez essayer ceci:

unzip -v /your/jar.jar

Cela ne sera utile que si votre fichier jar est exécutable, c'est-à-dire que dans le manifeste, vous avez défini une classe comme classe principale


1

Utilisez ce script bash:

#!/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

cela listera les classes à l'intérieur des jars de votre répertoire sous la forme:

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

Exemple de sortie:

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

Dans Windows, vous pouvez utiliser PowerShell:

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 "/", ".")
    }
}

0

Description de la solution : Eclipse IDE peut être utilisé pour cela en créant un exemple de projet java et en ajoutant tous les fichiers JAR dans le chemin de construction du projet

ÉTAPES ci - dessous :

  1. Créez un exemple de projet Java Eclipse.

  2. Tous les pots que vous avez dans son chemin de construction

  3. CTRL + SHIFT + T et tapez le nom complet de la classe.

  4. Les résultats seront affichés dans la fenêtre avec tous les pots ayant cette classe. Voir l'image ci-jointe. entrez la description de l'image ici


0

windows cmd: Cela fonctionnerait si vous avez tous les fichiers jars dans le même répertoire et exécutez la commande ci-dessous

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

0

Mac OS: sur le terminal:

vim <your jar location>

after jar gets opened, press / and pass your class name and hit enter
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.