Trouver une classe quelque part dans des dizaines de fichiers JAR?
Comment trouveriez-vous un nom de classe particulier dans beaucoup de fichiers jar?
(recherche du nom de classe réel, pas des classes qui le référencent.)
30 réponses
Eclipse peut le faire, il suffit de créer un projet (temporaire)et de placer vos bibliothèques sur le chemin de classe projects. Ensuite, vous pouvez facilement trouver les classes.
Un autre outil, qui me vient à l'esprit, est Java Decompiler. Il peut ouvrir beaucoup de pots à la fois et aide à trouver des classes aussi bien.
Unix
Utiliser le jar
(ou unzip -v
), grep
, et find
commandes.
Par exemple, ce qui suit liste tous les fichiers de classe qui correspondent à un nom donné:
for i in *.jar; do jar -tvf "$i" | grep -Hsi ClassName && echo "$i"; done
Si vous connaissez la liste complète des archives Java que vous souhaitez rechercher, vous pouvez les placer toutes dans le même répertoire en utilisant des liens (symboliques).
Ou utilisez find
(en tenant compte de la casse) pour trouver le fichier JAR contenant un nom de classe donné:
find path/to/libs -name '*.jar' -exec grep -Hls ClassName {} \;
Par exemple, Pour trouver le nom de l'archive contenant IdentityHashingStrategy
:
$ find . -name "*.jar" -exec grep -Hsli IdentityHashingStrategy {} \;
./trove-3.0.3.jar
Si le POT peut être n'importe où dans le système et la locate
commande est disponible:
for i in $(locate "*.jar");
do echo $i; jar -tvf $i | grep -Hsi ClassName;
done
Fenêtres
Ouvrez une invite de commande , passez au répertoire (ou au répertoire ancêtre) contenant les fichiers JAR, puis:
for /R %G in (*.jar) do @jar -tvf "%G" | find "ClassName" > NUL && echo %G
Voici comment cela fonctionne:
-
for /R %G in (*.jar) do
- parcourez tous les fichiers JAR en parcourant récursivement les répertoires; stockez le nom du fichier dans %G. -
@jar -tvf "%G" |
- exécutez Java Commande Archive pour lister tous les noms de fichiers dans l'archive donnée et écrire les résultats dans la sortie standard; le symbole@
supprime l'impression de l'invocation de la commande. -
find "ClassName" > NUL
- recherche d'entrée standard, canalisée à partir de la sortie de la commande jar, pour le nom de classe donné; cela définiraERRORLEVEL
à 1 s'il y a une correspondance (sinon 0). -
&& echo %G
- iffERRORLEVEL
est différent de zéro, écrivez le nom du fichier d'archive Java dans la sortie standard (la console).
Web
Utilisation un moteur de recherche qui analyse les fichiers JAR .
Il y a Quelques temps, j'ai écrit un programme juste pour ça: https://github.com/javalite/jar-explorer
grep -l "classname" *.jar
Vous donne le nom du pot
find . -name "*.jar" -exec jar -t -f {} \; | grep "classname"
Vous donne le paquet de la classe
#!/bin/bash
pattern=$1
shift
for jar in $(find $* -type f -name "*.jar")
do
match=`jar -tvf $jar | grep $pattern`
if [ ! -z "$match" ]
then
echo "Found in: $jar"
echo "$match"
fi
done
Je ne connaissais pas d'utilitaire pour le faire quand je suis tombé sur ce problème, alors j'ai écrit ce qui suit:
public class Main {
/**
*
*/
private static String CLASS_FILE_TO_FIND =
"class.to.find.Here";
private static List<String> foundIn = new LinkedList<String>();
/**
* @param args the first argument is the path of the file to search in. The second may be the
* class file to find.
*/
public static void main(String[] args) {
if (!CLASS_FILE_TO_FIND.endsWith(".class")) {
CLASS_FILE_TO_FIND = CLASS_FILE_TO_FIND.replace('.', '/') + ".class";
}
File start = new File(args[0]);
if (args.length > 1) {
CLASS_FILE_TO_FIND = args[1];
}
search(start);
System.out.println("------RESULTS------");
for (String s : foundIn) {
System.out.println(s);
}
}
private static void search(File start) {
try {
final FileFilter filter = new FileFilter() {
public boolean accept(File pathname) {
return pathname.getName().endsWith(".jar") || pathname.isDirectory();
}
};
for (File f : start.listFiles(filter)) {
if (f.isDirectory()) {
search(f);
} else {
searchJar(f);
}
}
} catch (Exception e) {
System.err.println("Error at: " + start.getPath() + " " + e.getMessage());
}
}
private static void searchJar(File f) {
try {
System.out.println("Searching: " + f.getPath());
JarFile jar = new JarFile(f);
ZipEntry e = jar.getEntry(CLASS_FILE_TO_FIND);
if (e == null) {
e = jar.getJarEntry(CLASS_FILE_TO_FIND);
if (e != null) {
foundIn.add(f.getPath());
}
} else {
foundIn.add(f.getPath());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Pour localiser les jars qui correspondent à une chaîne donnée:
find . -name \*.jar -exec grep -l YOUR_CLASSNAME {} \;
Il y a aussi deux utilitaires différents appelés "JarScan" qui font exactement ce que vous demandez: JarScan (inetfeedback.com) et JarScan (java.net)
Le script de
User1207523 fonctionne très bien pour moi. Voici une variante qui recherche les fichiers JAR de manière recusive en utilisant find au lieu d'une simple expansion;
#!/bin/bash
for i in `find . -name '*.jar'`; do jar -tf "$i" | grep $1 | xargs -I{} echo -e "$i : {}" ; done
J'ai toujours utilisé cela sur Windows et cela a exceptionnellement bien fonctionné.
findstr /s /m /c:"package/classname" *.jar, where
Findstr.exe est livré en standard avec Windows et les paramètres:
- /s = récursivement
- / m = affiche uniquement le nom du fichier s'il y a une correspondance
- / C = chaîne littérale (dans ce cas, votre nom de paquet + noms de classe séparé par'/')
J'espère que cela aide quelqu'un.
Une solution bash script
utilisant unzip (zipinfo)
. Testé sur Ubuntu 12
.
#!/bin/bash
# ./jarwalker.sh "/a/Starting/Path" "aClassName"
IFS=$'\n'
jars=( $( find -P "$1" -type f -name "*.jar" ) )
for jar in ${jars[*]}
do
classes=( $( zipinfo -1 ${jar} | awk -F '/' '{print $NF}' | grep .class | awk -F '.' '{print $1}' ) )
if [ ${#classes[*]} -ge 0 ]; then
for class in ${classes[*]}
do
if [ ${class} == "$2" ]; then
echo "Found in ${jar}"
fi
done
fi
done
J'ai trouvé cette nouvelle façon
bash $ ls -1 | xargs -i -t jar -tvf '{}'| grep Abstract
jar -tvf activation-1.1.jar
jar -tvf antisamy-1.4.3.jar
2263 Thu Jan 13 21:38:10 IST 2011 org/owasp/validator/html/scan/AbstractAntiSamyScanner.class
...
Donc, cela répertorie le jar et la classe si elle est trouvée, si vous le souhaitez, vous pouvez donner ls -1 *.jar ou entrée à xargs avec la commande find HTH Quelqu'un.
Vérifiez JBoss Tattletale ; bien que je ne l'ai jamais utilisé personnellement, cela semble être l'outil dont vous avez besoin.
Il suffit D'utiliser FindClassInJars util, c'est un programme swing simple, mais utile. Vous pouvez vérifier le code source ou télécharger le fichier jar à http://code.google.com/p/find-class-in-jars/
Je ne sais pas pourquoi les scripts ici n'ont jamais vraiment fonctionné pour moi. Cela fonctionne:
#!/bin/bash
for i in *.jar; do jar -tf "$i" | grep $1 | xargs -I{} echo -e "$i : {}" ; done
Pour rechercher tous les fichiers jar dans un répertoire donné pour une classe particulière, vous pouvez faire ceci:
ls *.jar | xargs grep -F MyClass
, Ou, encore plus simple,
grep -F MyClass *.jar
La sortie ressemble à ceci:
Binary file foo.jar matches
C'est très rapide car l'option-F signifie rechercher une chaîne fixe, donc elle ne charge pas le moteur regex pour chaque appel grep. Si vous en avez besoin, vous pouvez toujours omettre l'option-F et utiliser des expressions rationnelles.
Script pour trouver le fichier jar: find_jar.sh
IFS=$(echo -en "\n\b") # Set the field separator newline
for f in `find ${1} -iname *.jar`; do
jar -tf ${f}| grep --color $2
if [ $? == 0 ]; then
echo -n "Match found: "
echo -e "${f}\n"
fi
done
unset IFS
Utilisation:. /find_jar.sh
Ceci est similaire à la plupart des réponses données ici. Mais il ne génère que le nom du fichier, si grep trouve quelque chose. Si vous voulez supprimer la sortie grep, vous pouvez la rediriger vers /dev/null mais je préfère voir la sortie de grep afin que je puisse utiliser des noms de classe partiels et trouver le bon à partir d'une liste de sortie montrée.
Le le nom de classe peut être à la fois un nom de classe simple comme "String" ou un nom complet comme " java.lang.Chaîne "
Pour ajouter un autre outil... c'est un outil très simple et utile pour windows. Un simple fichier exe sur lequel vous cliquez, donnez-lui un répertoire pour rechercher, un nom de classe et il trouvera le fichier jar qui contient cette classe. Oui, c'est récursive.
, Vous pouvez trouver une classe dans un répertoire plein de pots avec un peu de shell:
Recherche de la classe "FooBar":
LIB_DIR=/some/dir/full/of/jarfiles
for jarfile in $(find $LIBDIR -name "*.jar"); do
echo "--------$jarfile---------------"
jar -tvf $jarfile | grep FooBar
done
Une chose à ajouter à tout ce qui précède: si vous n'avez pas l'exécutable jar disponible (il est livré avec le JDK mais pas avec le JRE), vous pouvez utiliser unzip (ou WinZip, ou autre) pour accomplir la même chose.
Auto promotion sans vergogne, mais vous pouvez essayer un utilitaire que j'ai écrit: http://sourceforge.net/projects/zfind
Il prend en charge les fichiers d'archive/compressés les plus courants (jar, zip, tar, tar.gz etc) et contrairement à beaucoup d'autres trouveurs jar/zip, prend en charge les fichiers zip imbriqués (zip dans zip, jar dans jar etc) jusqu'à une profondeur illimitée.
Un peu en retard à la fête, mais quand même...
J'ai utilisé JarBrowser pour trouver dans quel pot une classe particulière est présente. Il a une interface graphique facile à utiliser qui vous permet de parcourir le contenu de tous les pots dans le chemin sélectionné.
Le script suivant vous aidera
for file in *.jar
do
# do something on "$file"
echo "$file"
/usr/local/jdk/bin/jar -tvf "$file" | grep '$CLASSNAME'
done
Celui-ci fonctionne bien dans MinGW (Windows bash environment ) ~ gitbash
Mettez cette fonction dans votre .fichier bashrc dans votre répertoire personnel:
# this function helps you to find a jar file for the class
function find_jar_of_class() {
OLD_IFS=$IFS
IFS=$'\n'
jars=( $( find -type f -name "*.jar" ) )
for i in ${jars[*]} ; do
if [ ! -z "$(jar -tvf "$i" | grep -Hsi $1)" ] ; then
echo "$i"
fi
done
IFS=$OLD_IFS
}
Grepj est un utilitaire de ligne de commande pour rechercher des classes dans les fichiers jar. Je suis l'auteur de l'utilitaire.
, Vous pouvez exécuter l'utilitaire comme grepj package.Class my1.jar my2.war my3.ear
Plusieurs fichiers jar, ear, war peuvent être fournis. Pour une utilisation avancée, utilisez find pour fournir une liste de jars à rechercher.
Vérifiez ce Plugin pour eclipse qui peut faire le travail que vous recherchez.
Sous un environnement Linux, vous pouvez faire ce qui suit :
$ find <base_dir> -name *.jar -print0 | xargs -0 -l jar tf | grep <name>
Où nom est le nom du fichier de classe que vous recherchez à l'intérieur des fichiers JAR distribués dans la hiérarchie des répertoires enracinés _dir de base.
, Vous pouvez utiliser locate
et grep
:
locate jar | xargs grep 'my.class'
Assurez-vous d'exécuter updatedb
avant d'utiliser locate
.
Utilisez ceci.. vous pouvez trouver n'importe quel fichier dans classpath.. garantir..
import java.net.URL;
import java.net.URLClassLoader;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class FileFinder {
public static void main(String[] args) throws Exception {
String file = <your file name>;
ClassLoader cl = ClassLoader.getSystemClassLoader();
URL[] urls = ((URLClassLoader)cl).getURLs();
for(URL url: urls){
listFiles(file, url);
}
}
private static void listFiles(String file, URL url) throws Exception{
ZipInputStream zip = new ZipInputStream(url.openStream());
while(true) {
ZipEntry e = zip.getNextEntry();
if (e == null)
break;
String name = e.getName();
if (name.endsWith(file)) {
System.out.println(url.toString() + " -> " + name);
}
}
}
}