¿Encuentra una clase en algún lugar dentro de docenas de archivos JAR?

249

¿Cómo encontrarías un nombre de clase en particular dentro de muchos archivos jar?

(Buscando el nombre real de la clase, no las clases que lo hacen referencia).

Kapsh
fuente
1
No conozco ninguna de estas respuestas, pero lo que funciona para mí si ve la clase utilizada en un proyecto de trabajo con numerosos archivos JAR es colocar el cursor sobre el nombre de la clase, hacer clic con el botón derecho en él y hacer clic en Abrir declaración ( F3); entonces debería mostrar el archivo JAR en la parte superior de la nueva pestaña.
Andrew

Respuestas:

59

Eclipse puede hacerlo, solo crea un proyecto (temporal) y coloca tus bibliotecas en el classpath de proyectos. Entonces puedes encontrar fácilmente las clases.

Otra herramienta, que viene a mi mente, es Java Decompiler. Puede abrir muchos frascos a la vez y también ayuda a encontrar clases.

Andreas Dolk
fuente
22
y con la ayuda de Ctrl + Shift + T
KrishPrabakar
408

Unix

En Linux, otras variantes de Unix, Git Bash en Windows, o Cygwin, utilizar las jar(o unzip -v), grepy findcomandos.

A continuación se enumeran todos los archivos de clase que coinciden con un nombre dado:

for i in *.jar; do jar -tvf "$i" | grep -Hsi ClassName && echo "$i"; done

Si conoce la lista completa de archivos Java que desea buscar, puede colocarlos en el mismo directorio utilizando enlaces (simbólicos).

O use find(distingue entre mayúsculas y minúsculas) para encontrar el archivo JAR que contiene un nombre de clase dado:

find path/to/libs -name '*.jar' -exec grep -Hls ClassName {} \;

Por ejemplo, para encontrar el nombre del archivo que contiene IdentityHashingStrategy:

$ find . -name '*.jar' -exec grep -Hsli IdentityHashingStrategy {} \;
./trove-3.0.3.jar

Si el JAR podría estar en cualquier parte del sistema y el locatecomando está disponible:

for i in $(locate "*.jar");
  do echo "$i"; jar -tvf "$i" | grep -Hsi ClassName;
done

Una variación de sintaxis:

find path/to/libs -name '*.jar' -print | \
  while read i; do jar -tvf "$i" | grep -Hsi ClassName && echo "$i"; done 

Ventanas

Abra un símbolo del sistema , cambie al directorio (o directorio ancestro) que contiene los archivos JAR, luego:

for /R %G in (*.jar) do @jar -tvf "%G" | find "ClassName" > NUL && echo %G

Así es como funciona:

  1. for /R %G in (*.jar) do- recorrer todos los archivos JAR, recorriendo recursivamente directorios; almacenar el nombre del archivo en %G.
  2. @jar -tvf "%G" |- ejecute el comando Java Archive para enumerar todos los nombres de archivo dentro del archivo dado y escriba los resultados en la salida estándar; el @símbolo suprime la impresión de la invocación del comando.
  3. find "ClassName" > NUL- buscar entrada estándar, canalizada desde la salida del comando jar, para el nombre de clase dado; esto se establecerá ERRORLEVELen 1 si hay una coincidencia (de lo contrario 0).
  4. && echo %G- iff ERRORLEVELno es cero, escriba el nombre del archivo de almacenamiento Java en la salida estándar (la consola).

Web

Use un motor de búsqueda que escanee archivos JAR .

Dave Jarvis
fuente
3
Sí, te lo daré, pero no es muy útil cuando recibe su entrada de stdin.
George Armhold
60

Hace algún tiempo, escribí un programa solo para eso: https://github.com/javalite/jar-explorer

ipolevoy
fuente
44
Encuentra cualquier tipo de archivo, no solo clases. Haga doble clic para ver el contenido del archivo. Yay, ahora puedo ver todos mis esquemas de primavera.
Chris Noe
Increíble. Gracias;)
LppEdd
27
grep -l "classname" *.jar

te da el nombre de la jarra

find . -name "*.jar" -exec jar -t -f {} \; | grep  "classname"

te da el paquete de la clase

usuario311174
fuente
55
Debería ser grep -lir "classname" * .jar
Leonard Saers
12
#!/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
Pascal Lambert
fuente
Excelente ! Tuve que usarlo en un sistema que no tenía jar (no en la ruta, es decir), así que lo reemplacé jar -tvfcon unzip -l.
ixe013
9

Para localizar frascos que coinciden con una cadena dada:

find . -name \*.jar -exec grep -l YOUR_CLASSNAME {} \;

George Armhold
fuente
Esto también encuentra referencias a la clase, no solo a la clase misma.
Trevor Robinson
8

No conocía una utilidad para hacerlo cuando me encontré con este problema, así que escribí lo siguiente:

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

}
ILMTitan
fuente
4

El script user1207523 funciona bien para mí. Aquí hay una variante que busca archivos jar de forma recusiva usando find en lugar de una simple expansión;

#!/bin/bash
for i in `find . -name '*.jar'`; do jar -tf "$i" | grep $1 | xargs -I{} echo -e "$i : {}" ; done
Kurtcebe Eroglu
fuente
4

Siempre he usado esto en Windows y ha funcionado excepcionalmente bien.

findstr /s /m /c:"package/classname" *.jar, where

Findstr.exe viene estándar con Windows y los parámetros:

  • / s = recursivamente
  • / m = imprime solo el nombre de archivo si hay una coincidencia
  • / c = cadena literal (en este caso, su nombre de paquete + nombres de clase separados por '/')

Espero que esto ayude a alguien.

Ramesh Rooplahl
fuente
3

Una bash scriptsolución usando unzip (zipinfo). Probado en 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
Filippo Lauria
fuente
este script no es compatible con
mingw
2

Para buscar todos los archivos jar en un directorio dado para una clase en particular, puede hacer esto:

ls *.jar | xargs grep -F MyClass

o, incluso más simple,

grep -F MyClass *.jar

La salida se ve así:

Binary file foo.jar matches

Es muy rápido porque la opción -F significa buscar una cadena fija, por lo que no carga el motor de expresiones regulares para cada invocación grep. Si lo necesita, siempre puede omitir la opción -F y usar expresiones regulares.

Jeff
fuente
2

Encontré esta nueva forma

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
...

Entonces, esto enumera el jar y la clase si se encuentra, si lo desea, puede dar ls -1 * .jar o ingresar a xargs con el comando find HTH Someone.

Cleonjoys
fuente
Gracias, lo mejoro de esta manera: ls -1 * .jar | xargs -i -t jar -tvf '{}' | grep Resumen
Jérôme B
2

ClassFinder es un programa diseñado para resolver este problema. Le permite buscar de forma recursiva a través de directorios y archivos jar para encontrar todas las instancias de una clase que coincida con un patrón. Está escrito en Java, no en Python. Tiene una buena GUI que lo hace fácil de usar. Y corre rápido. Esta versión está precompilada en un jar ejecutable para que no tenga que compilarla desde la fuente.

Descárguelo aquí: ClassFinder 1.0

Gungwald
fuente
1

Compruebe JBoss Tattletale ; Aunque nunca lo he usado personalmente, esta parece ser la herramienta que necesita.

Wilfred Springer
fuente
1

No estoy seguro de por qué los guiones aquí nunca me han funcionado realmente. Esto funciona:

#!/bin/bash
for i in *.jar; do jar -tf "$i" | grep $1 | xargs -I{} echo -e "$i : {}" ; done
Mikael Lindlöf
fuente
1

Script para encontrar el archivo 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

Uso: ./find_jar.sh <directorio de nivel superior que contiene archivos jar> <Nombre de clase para buscar>

Esto es similar a la mayoría de las respuestas dadas aquí. Pero solo genera el nombre del archivo, si grep encuentra algo. Si desea suprimir la salida de grep, puede redirigir eso a / dev / null, pero también prefiero ver la salida de grep para poder usar nombres de clase parciales y encontrar el correcto de la lista de resultados que se muestra.

El nombre de la clase puede ser un nombre de clase simple como "String" o un nombre completo como "java.lang.String"

Joydip Datta
fuente
1

Para agregar otra herramienta más ... esta es una herramienta muy simple y útil para Windows. Un archivo exe simple en el que hace clic, le da un directorio para buscar, un nombre de clase y encontrará el archivo jar que contiene esa clase. Sí, es recursivo.

http://sourceforge.net/projects/jarfinder/

Ben
fuente
1

Para encontrar una clase en un grupo de carpetas (y subcarpetas) de 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

Ejemplo:

java -jar jarscan.jar -dir C:\Folder\To\Search -showProgress -class GenericServlet
KrishPrabakar
fuente
0

Puede encontrar una clase en un directorio lleno de jarras con un poco de shell:

Buscando la clase "FooBar":

LIB_DIR=/some/dir/full/of/jarfiles
for jarfile in $(find $LIBDIR -name "*.jar"); do
   echo "--------$jarfile---------------"
   jar -tvf $jarfile | grep FooBar
done
Steve B.
fuente
0

Una cosa para agregar a todo lo anterior: si no tiene el ejecutable jar disponible (viene con el JDK pero no con el JRE), puede usar descomprimir (o WinZip, o lo que sea) para lograr lo mismo.

Alex
fuente
0

autopromoción descarada, pero puedes probar una utilidad que escribí: http://sourceforge.net/projects/zfind

Admite los archivos comprimidos / archivos más comunes (jar, zip, tar, tar.gz, etc.) y, a diferencia de muchos otros buscadores de jar / zip, admite archivos zip anidados (zip dentro de zip, jar dentro de jar, etc.) hasta una profundidad ilimitada.

Dipankar Datta
fuente
0

Un poco tarde para la fiesta, pero sin embargo ...

He estado usando JarBrowser para encontrar en qué jar está presente una clase en particular. Tiene una GUI fácil de usar que le permite navegar a través del contenido de todos los frascos en la ruta seleccionada.

maccaroo
fuente
0

El siguiente script te ayudará

for file in *.jar
do
  # do something on "$file"
  echo "$file"
  /usr/local/jdk/bin/jar -tvf "$file" | grep '$CLASSNAME'
done
Kartik Jajal
fuente
0

Este funciona bien en MinGW (entorno de Windows bash) ~ gitbash

Ponga esta función en su archivo .bashrc en su directorio 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
}
kisp
fuente
0

Grepj es una utilidad de línea de comandos para buscar clases dentro de archivos jar. Soy el autor de la utilidad.

Puedes ejecutar la utilidad como grepj package.Class my1.jar my2.war my3.ear

Se pueden proporcionar múltiples archivos jar, ear, war. Para uso avanzado, use encontrar para proporcionar una lista de los frascos para buscar.

rrevo
fuente
0

En un entorno Linux, podría hacer lo siguiente:

$ find <base_dir> -name *.jar -print0 | xargs -0 -l jar tf | grep <name>

Donde nombre es el nombre del archivo de clase que está buscando dentro de los frascos distribuidos en la jerarquía de directorios enraizados en dir_base .

Víctor
fuente
0

Puedes usar locatey grep:

locate jar | xargs grep 'my.class'

Asegúrate de correr updatedbantes de usar locate.

mulugu mahesh
fuente