ChatGPT解决这个技术问题 Extra ChatGPT

Find a class somewhere inside dozens of JAR files?

How would you find a particular class name inside lots of jar files?

(Looking for the actual class name, not the classes that reference it.)

I don't know about any of these answers, but what works for me if you see the class used in a working project with numerous JAR files is to put your cursor on the class name, right click on it, and click Open Declaration (F3); then it should list the JAR file at the top of the new tab.

D
Dave Jarvis

Unix

On Linux, other Unix variants, Git Bash on Windows, or Cygwin, use the jar (or unzip -v), grep, and find commands.

The following lists all class files that match a given name:

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

If you know the entire list of Java archives you want to search, you could place them all in the same directory using (symbolic) links.

Or use find (case sensitively) to find the JAR file that contains a given class name:

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

For example, to find the name of the archive containing IdentityHashingStrategy:

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

If the JAR could be anywhere in the system and the locate command is available:

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

A syntax variation:

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

Windows

Open a command prompt, change to the directory (or ancestor directory) containing the JAR files, then:

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

Here's how it works:

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

Use a search engine that scans JAR files.


Yes -l will give you that, but not very useful when it's getting its input from stdin.
By far the best approach: all command line. Worked simply by pasting on a Windows Bash shell, found what I was looking for.
Brilliant - Just used the first one in Windows GitBash to locate two classes in an unknown jar file (I needed as I was getting stacktraces at SpringBoot jar launch) in a collection of 1580 third party JAR files in a directory!
A
Andreas Dolk

Eclipse can do it, just create a (temporary) project and put your libraries on the projects classpath. Then you can easily find the classes.

Another tool, that comes to my mind, is Java Decompiler. It can open a lot of jars at once and helps to find classes as well.


and with the help of Ctrl + Shift + T
i
ipolevoy

some time ago, I wrote a program just for that: https://github.com/javalite/jar-explorer


Finds any type of file, not just classes. Double-click to see file contents. Yay, now I can spot all my spring-schemas.
Awesome. Thanks ;)
u
user311174
grep -l "classname" *.jar

gives you the name of the jar

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

gives you the package of the class


It should be grep -lir "classname" *.jar
W
Whatsit
#!/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

Great ! I had to use it on a system that didn't have jar (not in the path, that is), so I replaced jar -tvf with unzip -l.
G
George Armhold

To locate jars that match a given string:

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


This finds references to the class as well, not just the class itself.
I
ILMTitan

I didn't know of a utility to do it when I came across this problem, so I wrote the following:

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

}

s
salzo

There are also two different utilities called both "JarScan" that do exactly what you are asking for: JarScan (inetfeedback.com) and JarScan (java.net)


G
Gungwald

ClassFinder is a program that's designed to solve this problem. It allows you to search recursively through directories and jar files to find all instances of a class matching a pattern. It is written in Java, not python. It has a nice GUI which makes it easy to use. And it runs fast. This release is precompiled in a runnable jar so you don't have to build it from source.

Download it here: ClassFinder 1.0


K
Kurtcebe Eroglu

user1207523's script works fine for me. Here is a variant that searches for jar files recusively using find instead of simple expansion;

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

R
Ramesh Rooplahl

I've always used this on Windows and its worked exceptionally well.

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

findstr.exe comes standard with Windows and the params:

/s = recursively

/m = print only the filename if there is a match

/c = literal string (in this case your package name + class names separated by '/')

Hope this helps someone.


F
Filippo Lauria

A bash script solution using unzip (zipinfo). Tested on 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

this script is not mingw compatible
K
KrishPrabakar

To find a class in a folder (and subfolders) bunch of JARs: 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

Example:

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

L
Liubing

Just use FindClassInJars util, it's a simple swing program, but useful. You can check source code or download jar file at http://code.google.com/p/find-class-in-jars/


m
maccaroo

A bit late to the party, but nevertheless...

I've been using JarBrowser to find in which jar a particular class is present. It's got an easy to use GUI which allows you to browse through the contents of all the jars in the selected path.


J
Jeff

To search all jar files in a given directory for a particular class, you can do this:

ls *.jar | xargs grep -F MyClass

or, even simpler,

grep -F MyClass *.jar

Output looks like this:

Binary file foo.jar matches

It's very fast because the -F option means search for Fixed string, so it doesn't load the the regex engine for each grep invocation. If you need to, you can always omit the -F option and use regexes.


C
Cleonjoys

I found this new way

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

So this lists the jar and the class if found, if you want you can give ls -1 *.jar or input to xargs with find command HTH Someone.


Thanks, I improve it this way : ls -1 *.jar | xargs -i -t jar -tvf '{}'| grep Abstract
B
Ben

To add yet another tool... this is a very simple and useful tool for windows. A simple exe file you click on, give it a directory to search in, a class name and it will find the jar file that contains that class. Yes, it's recursive.

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


W
Wilfred Springer

Check JBoss Tattletale; although I've never used it personally, this seems to be the tool you need.


M
Mikael Lindlöf

Not sure why scripts here have never really worked for me. This works:

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

J
Joydip Datta

Script to find jar file: 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

Usage: ./find_jar.sh < top-level directory containing jar files > < Class name to find>

This is similar to most answers given here. But it only outputs the file name, if grep finds something. If you want to suppress grep output you may redirect that to /dev/null but I prefer seeing the output of grep as well so that I can use partial class names and figure out the correct one from a list of output shown.

The class name can be both simple class name Like "String" or fully qualified name like "java.lang.String"


C
Collin Fox

Filename: 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 __name__ == "__main__":
    sys.exit(main())

You can easily run this by making a .bat file with the following text (replace "AddWorkflows.class" with the file you are searching for):

(File: CallSearchForFiles.bat)

@echo off
python -B -c "import searchForFiles;x=searchForFiles.main();" AddWorkflows.class
pause

You can double-click CallSearchForFiles.bat to run it, or call it from the command line "CallSearchForFiles.bat SearchFile.class"

Click to See Example Output


S
Steve B.

You can find a class in a directory full of jars with a bit of shell:

Looking for class "FooBar":

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

A
Alex

One thing to add to all of the above: if you don't have the jar executable available (it comes with the JDK but not with the JRE), you can use unzip (or WinZip, or whatever) to accomplish the same thing.


D
Dipankar Datta

shameless self promotion, but you can try a utility I wrote : http://sourceforge.net/projects/zfind

It supports most common archive/compressed files (jar, zip, tar, tar.gz etc) and unlike many other jar/zip finders, supports nested zip files (zip within zip, jar within jar etc) till unlimited depth.


n
nhahtdh

Following script will help you out

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

k
kisp

This one works well in MinGW ( windows bash environment ) ~ gitbash

Put this function into your .bashrc file in your HOME directory:

# 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
}

r
rrevo

Grepj is a command line utility to search for classes within jar files. I am the author of the utility.

You can run the utility like grepj package.Class my1.jar my2.war my3.ear

Multiple jar, ear, war files can be provided. For advanced usage use find to provide a list of jars to be searched.


k
kutty

Check this Plugin for eclipse which can do the job you are looking for.

https://marketplace.eclipse.org/content/jarchiveexplorer


V
Victor

Under a Linux environment you could do the following :

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

Where name is the name of the class file that you are looking inside the jars distributed across the hierarchy of directories rooted at the base_dir.