如何找到包含类定义的jar文件?

时间:2010-08-16 21:48:01

标签: java windows search class jar

在一堆jar文件中找到一个java类,你最喜欢的工具,插件,脚本是什么?

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

我显然更喜欢使用eclipse插件,但我对任何适用于Windows的软件都是开放的。

我知道...... Windows不是我的选择,但这就是我的工作。

谢谢!

路易斯

P.S。谢谢您的回答。在回顾了一些回复之后,我意识到我应该更好地解释我的情景。我们有一个下载或创建的JAR文件库,但有时候这个类会在某个地方上线。

17 个答案:

答案 0 :(得分:36)

(这是对我之前版本的答案中的脚本的改进,因为它以某些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)。通常我不打扰完整的类名,只需输入部分名称。

答案 1 :(得分:11)

与BalusC的答案相同(我无法发表评论,也无法链接2个网址,没有声誉:()),您可以通过这两个jar查找器引擎找到一个jar: - http://www.jarfinder.com/ - findjar

答案 2 :(得分:6)

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

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

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

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

如果您想查看来源,它位于同一网站: https://github.com/eurozulu/Findclass/tree/master

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

答案 3 :(得分:5)

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

我怀疑,也有一些窗户相同。

答案 4 :(得分:5)

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

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

答案 5 :(得分:2)

  

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

如果它不在类路径中,那么您可能根本就没有JAR文件。通过Eclipse的内置Ctrl+Shift+T函数进行搜索将无济于事。通常,您可以使用包名来“猜测”您可以从互联网上获取JAR文件的位置。例如。 http://commons.apache.org/lang提供org.apache.commons.lang.XXX课程。

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

答案 6 :(得分:2)

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

答案 7 :(得分:2)

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

答案 8 :(得分:2)

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

您可以像grepj package.Class my1.jar my2.war my3.ear

一样运行该实用程序

搜索范围

  • jar文件中的类
  • 嵌套工件中的类,如ear和war文件中的jar
  • 还搜索了WEB-INF / classes。

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

答案 9 :(得分:1)

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

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

该插件包含以下文件:

  1. temp 文件夹
  2. jad.exe 文件
  3. A * net.sf.jadclipse_3.3.0.jar * JAR插件
  4. 自述文件
  5. 执行以下步骤:

    1. 将JAR插件复制到eclipse文件夹的插件文件夹
    2. 打开日食。转到窗口&gt;&gt;偏好设置&gt;&gt; Java&gt;&gt; JADClipse&gt;&gt;反编译器的路径。
    3. 提供jad.exe的路径
    4. 重启Eclipse
    5. 现在选择任何一个班级并按F3。

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

答案 10 :(得分:1)

使用它:

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

答案 11 :(得分:1)

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

答案 12 :(得分:0)

我最近创建了一个搜索类,包和库的工具。你可以试试http://javasearch.buggybread.com/。单击框架,它将帮助您找到依赖项信息(jar,pom)。

答案 13 :(得分:0)

我尝试了一些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;
$options{wanted} = \&processFoundFile;
$options{no_chdir} = 1;
$options{follow} = 1; # So that $File::Find::fullname will be populated.
$options{follow_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 $options{follow} == 1

    # Windowize filename:
    $fullFileName = qx{cygpath --windows $fullFileName 2>&1};
    chomp $fullFileName;
    $fullFileName = '"' . $fullFileName . '"';

    my @results = qx{jar -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;
}

答案 14 :(得分:0)

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

答案 15 :(得分:0)

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

答案 16 :(得分:-1)

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

希望这有帮助