Comment trouveriez-vous un nom de classe particulier dans de nombreux fichiers jar?
(Recherche du nom de classe réel, pas des classes qui le référencent.)
Eclipse peut le faire, il suffit de créer un projet (temporaire) et de placer vos bibliothèques sur le classpath du projet. Ensuite, vous pouvez facilement trouver les classes.
Un autre outil qui me vient à l’esprit est Java Decompiler. Il peut ouvrir plusieurs bocaux à la fois et aide également à trouver des cours.
Utilisez les commandes jar
(ou unzip -v
), grep
et find
.
Par exemple, ce qui suit va lister 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 toutes les placer dans le même répertoire à l'aide de liens (symboliques).
Ou utilisez find
(sensible à 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 fichier JAR peut être n'importe où dans le système et que la commande locate
est disponible:
for i in $(locate "*.jar");
do echo $i; jar -tvf $i | grep -Hsi ClassName;
done
Ouvrez l'invite de commande , accédez au répertoire (ou répertoire des ancêtres) contenant les fichiers JAR, puis:
for /R %G in (*.jar) do @jar -tvf "%G" | find "ClassName" > NUL && echo %G
Voilà comment cela fonctionne:
for /R %G in (*.jar) do
- boucle sur tous les fichiers JAR, traversant les répertoires de manière récursive; enregistrer le nom du fichier dans% G.@jar -tvf "%G" |
- exécutez la commande Java Archive pour répertorier tous les noms de fichier de l'archive donnée et écrivez les résultats dans la sortie standard; le symbole @
supprime l’impression de l’appel de la commande.find "ClassName" > NUL
- recherche une entrée standard, issue de la sortie de la commande jar, pour le nom de classe donné; ERRORLEVEL
sera défini sur 1 ssi il y a une correspondance (sinon 0).&& echo %G
- si et seulement si ERRORLEVEL
est différent de zéro, écrivez le nom du fichier d'archive Java sur la sortie standard (la console).Utilisez un moteur de recherche qui analyse les fichiers JAR .
il y a quelque 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"
te 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 aucun utilitaire pour le résoudre lorsque je suis tombé sur ce problème. J'ai donc é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 bocaux correspondant à une chaîne donnée:
find . -name \*.jar -exec grep -l YOUR_CLASSNAME {} \;
Il existe également deux utilitaires différents appelés "JarScan" qui remplissent exactement ce que vous demandez: JarScan (inetfeedback.com) et JarScan (Java.net)
Je l'ai toujours utilisé sous Windows et cela a fonctionné exceptionnellement bien.
findstr /s /m /c:"package/classname" *.jar, where
findstr.exe est livré en standard avec Windows et les paramètres:
J'espère que ça aide quelqu'un.
le script de user1207523 me convient parfaitement. Voici une variante qui recherche les fichiers jar de manière récurrente en utilisant find au lieu de développement simple;
#!/bin/bash
for i in `find . -name '*.jar'`; do jar -tf "$i" | grep $1 | xargs -I{} echo -e "$i : {}" ; 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, ceci liste le jar et la classe si trouvé, si vous voulez, vous pouvez donner ls -1 * .jar ou une entrée à xargs avec la commande find HTH Someone.
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
Je ne sais pas pourquoi les scripts ici n'ont jamais vraiment fonctionné pour moi. Cela marche:
#!/bin/bash
for i in *.jar; do jar -tf "$i" | grep $1 | xargs -I{} echo -e "$i : {}" ; done
Il suffit d’utiliser FindClassInJars util, c’est un programme simple, mais utile. Vous pouvez vérifier le code source ou télécharger le fichier jar à l’adresse http://code.google.com/p/find-class-in-jars/
Vérifiez JBoss Tattletale ; Bien que je ne l'ait jamais utilisé personnellement, cela semble être l'outil dont vous avez besoin.
Pour rechercher une classe particulière dans tous les fichiers jar d'un répertoire donné, vous pouvez procéder comme suit:
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 la chaîne Fixed, de sorte qu'elle ne charge pas le moteur d'expression régulière pour chaque invocation de grep. Si vous en avez besoin, vous pouvez toujours omettre l’option -F et utiliser des expressions rationnelles.
Pour ajouter encore 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 dans lequel chercher, un nom de classe et il trouvera le fichier jar contenant cette classe. Oui, c'est récursif.
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 <répertoire de niveau supérieur contenant les fichiers JAR> <Nom de la classe à rechercher>
Ceci est similaire à la plupart des réponses données ici. Mais il ne sort que le nom du fichier, si grep trouve quelque chose. Si vous souhaitez supprimer la sortie de grep, vous pouvez le rediriger vers/dev/null, mais je préfère également voir la sortie de grep afin de pouvoir utiliser des noms de classe partiels et trouver le bon dans une liste de sortie affichée.
Le nom de la classe peut être à la fois un nom de classe simple, comme "String" ou un nom complet, tel que "Java.lang.String".
auto-promotion éhontée, mais vous pouvez essayer un utilitaire que j'ai écrit: http://sourceforge.net/projects/zfind
Il supporte les fichiers d'archive/compressés les plus courants (jar, Zip, tar, tar.gz, etc.) et contrairement à de nombreux autres détecteurs de jar/Zip, prend en charge les fichiers Zip imbriqués (Zip dans Zip, jar dans le bocal, etc.) jusqu'à une profondeur illimitée.
Pour rechercher une classe dans un groupe de dossiers (et de sous-dossiers) de fichiers JAR: https://jarscan.com/
Usage: Java -jar jarscan.jar [-help | /?]
[-dir directory name]
[-Zip]
[-showProgress]
<-files | -class | -package>
<search string 1> [search string 2]
[search string n]
Help:
-help or /? Displays this message.
-dir The directory to start searching
from default is "."
-Zip Also search Zip files
-showProgress Show a running count of files read in
-files or -class Search for a file or Java class
contained in some library.
i.e. HttpServlet
-package Search for a Java package
contained in some library.
i.e. javax.servlet.http
search string The file or package to
search for.
i.e. see examples above
Exemple:
Java -jar jarscan.jar -dir C:\Folder\To\Search -showProgress -class GenericServlet
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
Vous pouvez trouver une classe dans un répertoire plein de jars avec un peu de Shell:
Vous recherchez 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
Vérifiez ce plugin pour Eclipse qui peut faire le travail que vous recherchez.
Dans un environnement Linux, vous pouvez effectuer les opérations suivantes:
$ find <base_dir> -name *.jar -print0 | xargs -0 -l jar tf | grep <name>
Où name est le nom du fichier de classe que vous recherchez dans les fichiers JAR répartis dans la hiérarchie des répertoires situés à l'emplacement racine. base_dir .
Si vous avez une instance de la classe, ou pouvez en obtenir une, vous avez une solution pure Java:
try{
Class clazz = Class.forName(" try{
Class clazz = Class.forName("class-name");
String name = "/"+clazz.getName().replace('.', '/')+".class";
URL url = clazz.getResource(name);
String jar = url.toString().substring(10).replaceAll("!.*", "");
System.out.println( jar );
}catch(Exception err){
err.printStackTrace();
}
Bien sûr, les deux premières lignes doivent être adaptées en fonction de l'endroit où vous avez une instance de la classe ou du nom de la classe.
Celui-ci fonctionne bien dans MinGW (environnement Windows bash) ~ gitbash
Mettez cette fonction dans votre fichier .bashrc dans votre répertoire HOME:
# 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
}
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.
Nom de fichier: searchForFiles.py
import os, zipfile, glob, sys
def main():
searchFile = sys.argv[1] #class file to search for, sent from batch file below (optional, see second block of code below)
listOfFilesInJar = []
for file in glob.glob("*.jar"):
archive = zipfile.ZipFile(file, 'r')
for x in archive.namelist():
if str(searchFile) in str(x):
listOfFilesInJar.append(file)
for something in listOfFilesInJar:
print("location of "+str(searchFile)+": ",something)
if __== "__main__":
sys.exit(main())
Vous pouvez facilement exécuter cela en créant un fichier .bat avec le texte suivant (remplacez "AddWorkflows.class" par le fichier que vous recherchez):
(Fichier: CallSearchForFiles.bat)
@echo off
python -B -c "import searchForFiles;x=searchForFiles.main();" AddWorkflows.class
pause
Vous pouvez double-cliquer sur CallSearchForFiles.bat pour l'exécuter ou l'appeler à partir de la ligne de commande "CallSearchForFiles.bat SearchFile.class".
Vous pouvez utiliser locate
et grep
:
locate jar | xargs grep 'my.class'
Assurez-vous d’exécuter updatedb
avant d’utiliser locate
.
Dans Eclipse, vous pouvez utiliser l’ancien mais toujours utilisable plugin jarsearch
Grepj est un utilitaire de ligne de commande permettant de rechercher des classes dans des 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 des pots à rechercher.
Utilisez ceci .. vous pouvez trouver n'importe quel fichier dans classpath .. garanti ..
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);
}
}
}
}
Un peu tard pour la fête, mais quand même ...
J'ai utilisé JarBrowser pour trouver dans quel jar une classe particulière est présente. Il possède une interface graphique facile à utiliser qui vous permet de parcourir le contenu de tous les fichiers jars du chemin sélectionné.