在几十个JAR文件中找到一个类?

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

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

271095 次浏览

Eclipse可以做到这一点,只需创建一个(临时的)项目,并将您的库放在项目类路径上。然后你可以很容易地找到课程。

我想到的另一个工具是Java反编译器。它可以一次打开很多罐子,还可以帮助查找类。

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

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


}

Unix

在Linux、其他Unix变体、Windows上的Git Bash或Cygwin上,使用jar(或unzip -v)、grepfind命令。

下面列出了与给定名称匹配的所有类文件:

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

下面是它的工作原理:

  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 - iff ERRORLEVEL非零,将Java归档文件名写入标准输出(控制台)。

网络

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

你可以在一个充满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

检查JBoss 搬弄是非的人;虽然我个人从未使用过,但这似乎是你需要的工具。

除此之外,还有一件事需要补充:如果您没有可用的jar可执行文件(它随JDK而不是JRE一起提供),您可以使用unzip(或WinZip或其他任何工具)来完成同样的事情。

#!/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
grep -l "classname" *.jar

告诉你罐子的名字

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

给你类的包

只需使用FindClassInJars util,这是一个简单的swing程序,但很有用。你可以在http://code.google.com/p/find-class-in-jars/上查看源代码或下载jar文件

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

查找匹配给定字符串的jar:

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

无耻的自我推销,但你可以试试我写的实用程序:http://sourceforge.net/projects/zfind

它支持大多数常见的归档/压缩文件(jar, zip, tar, tar.gz等),不像许多其他jar/zip查找器,支持嵌套的zip文件(zip在zip, jar在jar等),直到无限的深度。

还有两个不同的实用程序叫做“JarScan”,可以完全满足您的要求: JarScan (inetfeedback.com)JarScan (java.net)

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

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

不知道为什么这里的脚本从来都不适合我。如此:

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

下面的脚本将帮助您

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

要搜索给定目录下的所有jar文件以查找特定的类,你可以这样做:

ls *.jar | xargs grep -F MyClass

或者更简单一点,

grep -F MyClass *.jar

输出如下所示:

Binary file foo.jar matches

它非常快,因为-F选项意味着搜索Fixed字符串,所以它不会为每次grep调用加载regex引擎。如果需要,您总是可以省略-F选项并使用正则表达式。

一个使用unzip (zipinfo)bash script解决方案。在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

User1207523的脚本对我来说很好。这里有一个变体,使用find隐式搜索jar文件,而不是简单的展开;

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

再加上一个工具……这是一个非常简单和有用的窗口工具。你点击一个简单的exe文件,给它一个目录来搜索,一个类名,它会找到包含该类的jar文件。是的,它是递归的。

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

这个在MinGW (windows bash环境)中工作得很好~ gitbash

把这个函数放到HOME目录下的.bashrc文件中:

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

Grepj是一个命令行实用程序,用于在jar文件中搜索类。我是这个实用程序的作者。

你可以像grepj package.Class my1.jar my2.war my3.ear那样运行这个实用程序

可以提供多个jar, ear, war文件。对于高级用法,使用find提供要搜索的jar列表。

查找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

使用方法:./find_jar.sh <包含jar文件> <的顶级目录;类名来查找>

这与这里给出的大多数答案相似。但是如果grep找到了什么,它只输出文件名。如果你想抑制grep输出,你可以重定向到/dev/null,但我更喜欢看到grep的输出,这样我就可以使用部分类名,并从显示的输出列表中找出正确的类名。

类名可以是简单类名如"String"也可以是完全限定名如"java.lang.String"

检查这个eclipse插件,它可以做你正在寻找的工作。

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

在Linux环境下,您可以执行以下操作:

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

其中< em >名称< / em >是类文件的名称,你在jar中查找的类文件分布在以< em > base_dir < / em >为根的目录层次结构中。

你可以使用locategrep:

locate jar | xargs grep 'my.class'

确保在使用locate之前运行updatedb

使用这个. .你可以在类路径..中找到任何文件。保证. .

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


}

我找到了这个新方法

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

如果你想,你可以给ls -1 *.jar,或者用查找命令HTH Someone输入xargs。

在eclipse中,你可以使用旧的但仍然可用的插件jarsearch

我一直在Windows上使用它,效果非常好。

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

findstr.exe是Windows和参数的标准配置:

  • /s =递归
  • /m =如果有匹配,只打印文件名
  • /c =字面字符串(在这种情况下,你的包名+类名 以'/'分隔)

希望这能帮助到一些人。

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

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

在一个jar文件夹(及其子文件夹)中找到一个类: https://jarscan.com/ < / p >
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

例子:

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

文件名: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())

你可以通过创建一个带有以下文本的.bat文件(用你正在搜索的文件替换“AddWorkflows.class”)来轻松运行:

(文件:CallSearchForFiles.bat)

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

您可以双击CallSearchForFiles.bat来运行它,或者从命令行“CallSearchForFiles.bat SearchFile.class”调用它。

点击查看输出示例

ClassFinder是一个专门用来解决这个问题的程序。它允许您在目录和jar文件中递归搜索,以找到与模式匹配的类的所有实例。它是用Java编写的,而不是python。它有一个很好的图形用户界面,这使得它易于使用。它跑得很快。这个版本是在一个可运行的jar中预编译的,所以您不必从源代码构建它。

在这里下载:ClassFinder 1.0

我知道这是一个老问题,但是…
我也有同样的问题,所以如果有人正在寻找一个非常简单的解决方案的windows -有一个软件名为Locate32 只需将jar文件扩展名为
并包含类名

Locate32 in action