Найти класс где-то внутри десятков JAR-файлов? - PullRequest
227 голосов
/ 27 августа 2009

Как бы вы нашли конкретное имя класса во множестве jar-файлов?

(ищет фактическое имя класса, а не классы, которые ссылаются на него.)

Ответы [ 34 ]

367 голосов
/ 27 августа 2009

Unix

Используйте команды jar (или unzip -v), grep и find.

Например, в следующем списке перечислены все файлы классов, которыесоответствует заданному имени:

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

Если вам известен весь список Java-архивов, которые вы хотите найти, вы можете поместить их все в один каталог, используя (символические) ссылки.

Илииспользуйте find (чувствительно к регистру), чтобы найти файл JAR, который содержит заданное имя класса:

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

Например, чтобы найти имя архива, содержащего IdentityHashingStrategy:

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

Если JAR может быть в любом месте в системе и доступна команда locate:

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

Windows

Открыть командная строка , перейдите в каталог (или каталог предков), содержащий файлы JAR, затем:

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

Вот как это работает:

  1. for /R %G in (*.jar) do - перебрать все файлы JAR, рекурсивно обходя каталоги;сохранить имя файла в% G.
  2. @jar -tvf "%G" | - запустить команду Java Archive, чтобы получить список всех имен файлов в данном архиве и записать результаты в стандартный вывод;символ @ подавляет печать вызова команды.
  3. find "ClassName" > NUL - поиск стандартного ввода, переданного по выводу команды jar, для заданного имени класса;это установит ERRORLEVEL в 1, если есть совпадение (в противном случае 0).
  4. && echo %G - если ERRORLEVEL не равно нулю, запишите имя файла архива Java в стандартный вывод (консоль).

Web

Используйте поисковую систему , которая сканирует JAR-файлы .

57 голосов
/ 01 июля 2011

некоторое время назад я написал программу только для этого: https://github.com/javalite/jar-explorer

54 голосов
/ 27 августа 2009

Eclipse может это сделать, просто создайте (временный) проект и поместите свои библиотеки в путь к классам проектов. Тогда вы можете легко найти классы.

Другой инструмент, который приходит мне в голову, это Java Decompiler. Он может открыть много банок одновременно и помогает найти классы.

23 голосов
/ 22 марта 2011
grep -l "classname" *.jar

дает вам имя банки

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

дает вам пакет класса

11 голосов
/ 07 января 2011
#!/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
7 голосов
/ 27 августа 2009

Я не знал об утилите для этого, когда столкнулся с этой проблемой, поэтому написал следующее:

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

}
7 голосов
/ 03 апреля 2012

Чтобы найти банки, которые соответствуют заданной строке:

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

5 голосов
/ 08 августа 2012

Есть также две разные утилиты, которые называются JarScan и выполняют именно то, что вы просите: JarScan (inetfeedback.com) и JarScan (java.net)

3 голосов
/ 19 июля 2013

Скрипт user1207523 отлично работает для меня. Вот вариант, который ищет файлы jar с использованием find вместо простого расширения;

#!/bin/bash
for i in `find . -name '*.jar'`; do jar -tf "$i" | grep $1 | xargs -I{} echo -e "$i : {}" ; done
3 голосов
/ 21 октября 2016

Я всегда использовал это в Windows, и оно работало исключительно хорошо.

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

findstr.exe стандартно поставляется с Windows и параметрами:

  • / s = рекурсивно
  • / m = выводить только имя файла, если есть совпадение
  • / c = буквальная строка (в данном случае имя вашего пакета + имена классов разделены знаком '/')

Надеюсь, это кому-нибудь поможет.

...