如何找到包含类定义的jar文件? [关闭]

Posted

技术标签:

【中文标题】如何找到包含类定义的jar文件? [关闭]【英文标题】:how to find the jar file containing a class definition? [closed] 【发布时间】:2011-03-30 16:28:14 【问题描述】:

是否有工具、插件或脚本可以用来在一堆 jar 文件中查找 java 类?

我经常继承抱怨不存在的类的代码,这只是因为 jar 文件未包含在类路径中。但是,类在什么 jar 文件中?我可能没有 JAR(所以我必须在线搜索),或者将 JAR 添加到类路径可能会产生重复的类定义问题。

我显然更喜欢 Eclipse 插件,但我愿意接受任何适用于 Windows 的软件。

我知道...Windows 不是我的选择,但这就是我必须使用的。

谢谢!

路易斯

附:谢谢您的回答。在查看了一些回复后,我意识到我应该更好地解释我的场景。我们有一个下载或创建的 JAR 文件库,但有时课程会在某个地方在线。

【问题讨论】:

好问题。我一直遇到这个。不知道为什么它被关闭为题外话。奇怪 这就是你的 ***。 【参考方案1】:

我通常为此使用 bash:grep -lr "ClassName" . 诀窍是名称不会以任何方式编码。您可以在文本编辑器中打开 jar 文件,您会看到它们。 (您甚至可以在搜索查询中包含包名称。)

我怀疑,也有一些 Windows 等价物。

【讨论】:

是的,但问题是很难判断文件是否包含类的定义或使用。而且,是的,有一个可以下载的 grep 实用程序。谢谢! @luiscolorado 以前从来没有给我误报过。我不知道,可能大部分内容(包括引用的类)都以某种方式编码。 Mmmmmhh... 不幸的是我得到了一堆误报。或者可能是因为该类在多个包中具有相同的名称。无论如何,我会再试一次。谢谢,尼基塔!【参考方案2】:

您总是可以在 Eclipse 中将参考库添加到您的项目中,然后在包浏览器中,只需展开 JAR 文件中的包,直到找到您要查找的类。

【讨论】:

当然!虽然我在寻找更快的东西:) 我必须在这个项目中列出 20 个 jar 文件,谁知道有多少类。 对于构建路径上的 jars,只需使用 Ctrl-Shift-T 来定位一个类。 仍然不是我的那杯茶,但我们拭目以待。【参考方案3】:

@Nikita Rybak:AstroGrep for Windows 是我们的朋友:http://astrogrep.sourceforge.net/

【讨论】:

我喜欢 AstroGrep!与命令行版本相比,我发现它很友好。但是,它与任何 grep 都有相同的问题(请参阅我对 Nikita Rybak 的评论)。 True... 但是 使用 AstroGrep 您可以将其设置为返回 +/- N 行数。所以这当然不是最好的选择,但它可能会奏效。【参考方案4】:

我经常继承抱怨一个不存在的类的代码,这只是因为 jar 文件未包含在类路径中。

如果它不在类路径中,那么您可能根本没有 JAR 文件本身。通过 Eclipse 的内置 Ctrl+Shift+T 函数搜索不会有太大帮助。通常你可以利用包名来“猜测”你可以从互联网上从哪里得到 JAR 文件。例如。 org.apache.commons.lang.XXX 课程可在 http://commons.apache.org/lang 获得。

对于不明显的,我自己使用http://grepcode.com,JAR 源代码搜索引擎。

【讨论】:

如果它不在类路径中,那么您可能根本没有 JAR 文件本身 嗯,我经常遇到 jboss。数百个内部库,您通常只需要很少的库来编译您的代码。不过,感谢您的链接,这很有趣。 @Nikita:在这种特定情况下,您希望将动态 Web 项目的目标服务器更新为 JBoss。 嘘...... 8 年后仍然无法使用!我认为 Maven Repo 应该提供这个......它拥有所有的东西......它所要做的“所有”就是保持一个最新的 Lucene 索引,是的,它的所有 .jar 中的每个类!跨度> 【参考方案5】:

使用这个:

public class Main 

    private static final String SEARCH_PATH = "C:\\workspace\\RPLaunch";
    private static String CLASS_FILE_TO_FIND =
            "javax.ejb.SessionBean";
    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) 
        File start;
        new Scanner(args[0]);
        if (args.length > 0) 
            start = new File(args[0]);
            if (args.length > 1) 
                CLASS_FILE_TO_FIND = args[1];
            
         else 
            start = new File(SEARCH_PATH);
        
        if (!CLASS_FILE_TO_FIND.endsWith(".class")) 
            CLASS_FILE_TO_FIND = CLASS_FILE_TO_FIND.replace('.', '/') + ".class";
        
        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());
            
         catch (IOException e) 
            e.printStackTrace();
        
    

【讨论】:

【参考方案6】:

在与 BalusC 的答案相同的行中(我还不能发表评论,也不能链接 2 个 url,没有声誉 :(),由于这 2 个 jar finder 引擎,你可以找到一个 jar: - http://www.jarfinder.com/ - 查找罐

【讨论】:

网站已移至:findjar.com【参考方案7】:

我为此编写了一个程序:https://github.com/javalite/jar-explorer 它还会反编译现有的字节码以显示接口、方法、超类,将显示其他资源的内容 - 文本、图像、html 等。

【讨论】:

谢谢!!好工具!!! 我正在使用你的工具,但我遇到了一些错误:OpenJDK 64-Bit Server VM warning: INFO: os::commit_memory(0x00000000ebcff000, 196608, 0) failed; error='Cannot allocate memory' (errno=12) # # 内存不足,Java 运行时环境无法继续。 # 本机内存分配 (mmap) 未能映射 196608 字节以提交保留内存。 # 包含更多信息的错误报告文件保存为: # /host/tools/jar-explorer/target/hs_err_pid6786.log 它不打算与 OpenJDK 一起使用吗?是否有建议分配给此 JAR 的内存量? 不知道为什么。我刚刚在 OpenJDK 版本 8 上运行它,它按预期工作。您可以下载源代码并使用 JDK 在本地构建。它没有依赖关系,因此构建很容易【参考方案8】:

我无数次遇到同样的问题,所以我写了一个小工具来找到它们。

一个简单的命令行: findclass MyClass -classpath ...

它会为您的班级搜索目录、jar、zip、war 和 ear 文件。 几年前我写了它并一直使用它。 我想其他人可能也会觉得它有用,所以我上传到了 github。

它可以免费下载: https://github.com/eurozulu/Findclass/tree/master/dist

如果您想查看源代码,它位于同一个站点中: https://github.com/eurozulu/Findclass/tree/master

如果你喜欢它,请告诉我,给我那种温暖舒适的感觉 :)

【讨论】:

我发现你的工具很有用。谢谢!【参考方案9】:

我使用jarscan。它是一个可执行的 jar 文件,可以递归地在整个文件夹结构中搜索包含您要查找的类的 jar。它按类名、包名或正则表达式搜索。

【讨论】:

【参考方案10】:

(这是对我在以前版本的答案中的脚本的改进,因为它以一些 awk 特殊/丑陋的引用的价格产生了更清晰的输出。)

我已经构建了一个脚本 (findinjars),它就是这样做的。

#!/usr/bin/env bash
if [[ ($# -ne 1) && ($# -ne 2) ]]
then
    echo "usage is $0 <grep pattern to look for in 'jar tvf' output> [<top-of-dir-tree> or, if missing, current dir]"
else
    THING_TO_LOOKFOR="$1"
    DIR=$2:-.
    if [ ! -d $DIR ]; then
        echo "directory [$DIR] does not exist";
        exit 1;
    fi
    find "$DIR" -iname \*.jar | while read f ; do (jar tf $f | awk 'print "'"$f"'" "  " $0' | grep -i "$THING_TO_LOOKFOR") ; done
fi

然后你可以调用它:

$findinjars a.b.c.d.Class [directoryTreeRoot or, if missing, current dir]

或者只是

$findinjars partOfClassName [directoryTreeRoot or, if missing, current dir]

完全限定类名中的点字符将被解释为“任何字符”的正则表达式,但这没什么大不了的,因为这是一个启发式实用程序(这就是为什么它也不区分大小写 BTW)。通常我不关心完整的类名,只输入其中的一部分。

【讨论】:

【参考方案11】:

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

您可以像grepj package.Class my1.jar my2.war my3.ear一样运行该实用程序

搜索范围是

jar 文件中的类 嵌套工件中的类,例如 ear 和 war 文件中的 jars WEB-INF/classes 也会被搜索。

可以提供多个jar、ear、war文件。

【讨论】:

【参考方案12】:

这里只想提一下,第三方可以在jarfinder中搜索一些特定的文件名 虽然它没有直接回答问题,但它不会伤害:)

希望对你有帮助

【讨论】:

这本质上是一个链接的答案。此外,已经提供了它的链接,实际上是投票最多的答案。你忍了三年【参考方案13】:

一个更简单的命令。您不必使用 'while-do',如果 'grep' 找到类,则使用 '&&' 打印文件名。

find . -name '*.jar' -print0 |  xargs -0 -I '' sh -c 'jar tf  | grep Hello.class &&  echo '

【讨论】:

【参考方案14】:

for x in $(find .-name '*.jar') 做 解压-l $x | grep WCCResponseImpl 完成

【讨论】:

【参考方案15】:

我尝试了其中一些 Unix 命令,但由于各种原因它们出错了。这是我编写的 Perl 脚本。它专门设计用于使用 Cygwin 版本的 Perl 在 Cygwin 上运行。

#!/bin/perl

# This program searches recursively for a given class in .jar files contained in or below
# directories given as command-line arguments. See subroutine printUsageAndExit for details,
# or just run it with -h command-line argument.
#
# It is specfically designed to run on Windows via Cygwin, with Cygwin's version of Perl,
# though it could easily be modified to run elsewhere.

use strict;
use File::Find;
use Getopt::Std;

sub processCommandLineArguments (\$\@);
sub checkCommandLineArguments;

my $className;
my @startingDirectories;

&checkCommandLineArguments;
&processCommandLineArguments (\$className, \@startingDirectories );

my %options;
$optionswanted = \&processFoundFile;
$optionsno_chdir = 1;
$optionsfollow = 1; # So that $File::Find::fullname will be populated.
$optionsfollow_skip = 2; # So it won't die if it encounters the same thing twice.

&find ( \%options, @startingDirectories );  # find comes from "use File::Find".

sub processFoundFile
    # This routine is called by File::Find.
    #
    #  $File::Find::dir is the current directory name,
    #  $_ is the current filename within that directory
    #  $File::Find::name is the complete pathname to the file.

    my $jarFileName = $_;

    return unless /\.jar$/;

    my $fullFileName = $File::Find::fullname; # set by File::Find only when $optionsfollow == 1

    # Windowize filename:
    $fullFileName = qxcygpath --windows $fullFileName 2>&1;
    chomp $fullFileName;
    $fullFileName = '"' . $fullFileName . '"';

    my @results = qxjar -tf $fullFileName 2>&1;

    local $/ = "\r\n";  # So that this Unix-based Perl can read output from Windows based jar command.

    for my $result ( @results )
    
        chomp $result;

        if ( $result =~ /\b(\w+)\.((java)|(class))$/ )
        
            my $classNameFound = $1;

            if ($classNameFound eq $className)
            
                print $jarFileName, "\n";
                return;
            
        
    


sub processCommandLineArguments (\$\@)

    my $refClassName = shift;
    my $refStartingDirectories = shift;

    $$refClassName = '';

    # parse @ARGV
    while (@ARGV)
        my $arg = shift @ARGV;

        if ($arg =~ /\Q-c/)
            $$refClassName = shift @ARGV;
        elsif ($arg =~ /\Q-directories/)

            while ($ARGV[0] =~ m^/(\w+/?)+\b)
                my $directory = shift @ARGV;
                die "Can't find $directory $!" if ! -e $directory;
                push @$refStartingDirectories, $directory;
            
        
    

    die "Must give -c class_name argument $!" if $$refClassName eq "";

    push @$refStartingDirectories, '.' if scalar (@$refStartingDirectories ) == 0;


sub checkCommandLineArguments

    
        # getopts butchers @ARGV, so have to use it on a local version.
        local @ARGV = @ARGV;

        our $opt_h;
        &getopts('hc'); # Have to specify all options given or getopts will die.

        &printUsageAndExit if $opt_h;
    

    my $className;

    
        # getopts butchers @ARGV, so have to use it on a local version.
        local @ARGV = @ARGV;

        while (@ARGV)
            my $arg = shift @ARGV;

            if ($arg =~ /\Q-c/)
                $className = shift @ARGV;

                &printUsageAndExit if $className =~ /^\s*$/ ;

                return;
            
        
    

    &printUsageAndExit;


sub printUsageAndExit

    print "Usage:\n\n";
    print "$0 -c class_name_to_search_for [ -directories startingDirectory1 startingDirectory2 ...]\n\n";
    print "Example:\n\n";
    print "findJarContainingClass.pl -c ApplicationMaster -directories /home/lylez/Hadoop/hadoop-2.x/hadoop-2.2.0/share/hadoop/yarn/sources /home/lylez/Hadoop/hadoop-2.x/hadoop-2.2.0/share/hadoop/yarn\n\n";

    exit;

【讨论】:

【参考方案16】:

最好和最简单的方法是使用 JAD 反编译器。是的,它是一个 ECLIPSE 插件

Download 并将插件保存在您机器上的任何位置。

插件包含以下文件:

    temp 文件夹 一个 jad.exe 文件 *net.sf.jadclipse_3.3.0.jar* JAR 插件 自述文件

执行以下步骤:

    将JAR插件复制到eclipse文件夹的plugins文件夹中 打开日食。转到窗口 >> 首选项 >> Java >> JADClipse >> 反编译器路径。 给出jad.exe的路径 重启 Eclipse

现在选择任意班级并按 F3。

.class 文件会自动反编译并显示内容!

【讨论】:

【参考方案17】:

我最近创建了一个搜索类、包和库的工具。你可以试试http://javasearch.buggybread.com/。点击框架,它会帮你定位依赖信息(jar,pom)。

【讨论】:

链接似乎已失效 现在可以使用了。

以上是关于如何找到包含类定义的jar文件? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

是否可以创建一个包含项目类和项目依赖项的“uber”jar 作为带有自定义清单文件的 jar?

如何反编译整个Jar文件? [关闭]

在几十个 JAR 文件中的某个地方找到一个类?

maven构建我的项目时无法从库项目的jar中找到类

包含 Eclipse 和可运行 Jar 的资源

jar 或类混淆的最佳工具,无需编写任何额外的配置文件 [关闭]