如何在大量jar文件中找到特定的类名?

(查找实际的类名,而不是引用它的类。)


当前回答

不久前,我专门为此写了一个程序:https://github.com/javalite/jar-explorer

其他回答

有点晚了,但无论如何……

我一直在使用JarBrowser查找在哪个jar中存在一个特定的类。它有一个易于使用的图形用户界面,允许您浏览所选路径中所有罐子的内容。

如果你有一个类的实例,或者可以得到一个,你有一个纯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();
    }

当然,前两行必须根据类的实例或类名的位置进行调整。

当我遇到这个问题时,我不知道有什么实用程序可以做到这一点,所以我写了下面的代码:

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

}

你可以在一个充满jar的目录中找到一个类,它带有一些shell:

寻找类“FooBar”:

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

Unix

在Linux、其他Unix变体、Windows上的Git Bash或Cygwin上,使用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

语法变化:

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

窗户

打开命令提示符,切换到包含JAR文件的目录(或祖先目录),然后:

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

下面是它的工作原理:

for /R %G in (*.jar) do - loop over all JAR files, recursively traversing directories; store the file name in %G. @jar -tvf "%G" | - run the Java Archive command to list all file names within the given archive, and write the results to standard output; the @ symbol suppresses printing the command's invocation. find "ClassName" > NUL - search standard input, piped from the output of the jar command, for the given class name; this will set ERRORLEVEL to 1 iff there's a match (otherwise 0). && echo %G - iff ERRORLEVEL is non-zero, write the Java archive file name to standard output (the console).

Web

使用扫描JAR文件的搜索引擎。