web-dev-qa-db-fra.com

comment trouver le fichier jar contenant une définition de classe?

Quel est votre outil préféré, plugin, script, pour trouver une classe Java dans un tas de fichiers jar?

Très souvent, j'hérite d'un code qui se plaint d'une classe qui n'existe pas, c'est simplement parce que le fichier jar n'est pas inclus dans le chemin d'accès aux classes. Mais dans quel (s) fichier (s) jar est la classe? Je n'ai peut-être pas le fichier JAR (je dois donc effectuer une recherche en ligne), ou l'ajout d'un fichier JAR au chemin de classe peut créer un problème de définition de classe en double.

Je préférerais évidemment un plugin Eclipse, mais je suis ouvert à tout logiciel fonctionnant sous Windows.

Je sais ... Windows n’est pas mon choix, mais c’est avec ça que je dois travailler.

Merci!

Luis

P.S. Merci pour vos réponses. Après avoir examiné certaines réponses, je me suis rendu compte que j'aurais dû mieux expliquer mon scénario. Nous avions une bibliothèque de fichiers JAR téléchargés ou créés, mais parfois, la classe était en ligne quelque part. 

28
luiscolorado

(Il s'agit d'une amélioration par rapport au script que j'avais dans les versions précédentes de la réponse, car il produit une sortie beaucoup plus propre au prix d'une citation awk spéciale/moche.)

J'ai construit un script (findinjars) qui fait justement cela.

#!/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

vous pouvez alors l'invoquer avec:

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

ou juste 

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

Les points dans le nom de classe qualifié complet seront interprétés dans le sens regexp de «n'importe quel caractère», mais ce n'est pas grave car il s'agit d'un utilitaire heuristique (c'est pourquoi il est insensible à la casse aussi). D'habitude, je ne m'embête pas avec le nom complet de la classe et en tape simplement une partie.

35

Dans les mêmes lignes que la réponse de BalusC (je ne peux pas encore publier de commentaire, ni associer 2 URL, pas de réputation :(), vous pouvez trouver un bocal grâce à ces 2 moteurs de recherche de bocaux: - http: // www .jarfinder.com/ / - findjar

11
Fanny H.

J'ai rencontré le même problème d'innombrables fois, alors j'ai écrit un petit outil pour les trouver.

Une ligne de commande simple: Findclass MyClass -classpath ...

Il recherche dans votre classe les répertoires, les fichiers jar, Zip, war et ear . Je l’ai écrit il ya quelques années et je l’utilise tout le temps .

Il est disponible gratuitement au téléchargement: https://github.com/eurozulu/Findclass/tree/master/dist

Si vous souhaitez consulter la source, elle se trouve sur le même site: https://github.com/eurozulu/Findclass/tree/master

Si vous l'aimez, faites le moi savoir pour me donner ce sentiment chaleureux et confortable :)

6
Rob

Une commande plus simple. Vous n'avez pas besoin d'utiliser 'while-do', utilisez '&&' pour imprimer le nom du fichier si 'grep' trouve la classe.

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

J'utilise habituellement bash pour cela: grep -lr "ClassName" . L'astuce est que les noms ne sont pas encodés de quelque manière que ce soit. Vous pouvez ouvrir le fichier jar dans l'éditeur de texte et vous le verrez. (Vous pouvez même inclure le nom du package dans la requête de recherche.)

Je soupçonne qu’il ya aussi l’équivalent Windows.

5
Nikita Rybak

Grepj est un utilitaire de ligne de commande permettant de rechercher des classes dans des fichiers jar.

Vous pouvez exécuter l'utilitaire comme grepj package.Class my1.jar my2.war my3.ear

Le champ de recherche est

  • Classes dans le fichier jar
  • Classes dans des artefacts imbriqués, tels que des pots dans des fichiers ear et war
  • WEB-INF/classes est également recherché.

Plusieurs fichiers jar, ear, war peuvent être fournis.

2
rrevo

J'utilise jarscan . Il s'agit d'un fichier jar exécutable qui peut rechercher de manière récursive une structure de dossiers complète pour les jars contenant la classe que vous recherchez. Il recherche par nom de classe, nom de paquet ou regex.

2
Mike Pone

J'ai écrit un programme pour cela: https://github.com/javalite/jar-Explorer Il décompilera également le code octet existant pour vous montrer les interfaces, méthodes, super classes, montrera le contenu d'autres ressources - text , images, html, etc.

2
ipolevoy

Très souvent, j'hérite d'un code qui se plaint d'une classe qui n'existe pas, c'est simplement parce que le fichier jar n'est pas inclus dans le chemin d'accès aux classes.

Si ce n'est pas dans le chemin de classe, vous n'avez probablement pas le fichier JAR lui-même. Rechercher avec la fonction Ctrl+Shift+T intégrée d'Eclipse n'aidera pas grand chose. Habituellement, vous pouvez utiliser le nom du paquet pour "deviner" où vous pouvez obtenir le fichier JAR sur Internet. Par exemple. une classe org.Apache.commons.lang.XXX est disponible sur http://commons.Apache.org/lang

Pour les non-évidents, j’utilise moi-même http://grepcode.com , le moteur de recherche de code source JAR.

2
BalusC

utilisez ceci:

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

La meilleure et la plus simple consiste à utiliser le décompresseur JAD. Et oui, c’est un Eclipse PLUGIN!

Téléchargez et enregistrez le plug-in à n’importe quel emplacement sur votre ordinateur. 

Le plugin contient les fichiers suivants:

  1. Un dossier temp
  2. Un fichier jad.exe
  3. Un plugin * net.sf.jadclipse_3.3.0.jar * JAR
  4. Un readme 

Effectuez les étapes suivantes:

  1. Copiez le plugin JAR dans le dossier plugins du dossier Eclipse.
  2. Ouvrez Eclipse. Aller à la fenêtre >> Préférences >> Java >> JADClipse >> Chemin vers Decompiler.
  3. Donner le chemin de jad.exe
  4. Redémarrer Eclipse

Maintenant, sélectionnez une classe et appuyez sur F3.

Le fichier .class va automatiquement décompiler et afficher le contenu! 

1
Neal

pour x dans $ (find. -name '* .jar') do unzip -l $ x | grep WCCResponseImpl done

1
user2981289

J'ai récemment créé un outil pour rechercher des classes, des packages et des bibliothèques. Vous pouvez l'essayer http://javasearch.buggybread.com/ . Cliquez sur le framework et cela vous aidera à localiser les informations de dépendance (jar, pom).

0
Vivek Vermani

J'ai essayé certaines de ces commandes Unix, mais elles ont été erronées pour diverses raisons. Voici un script Perl que j'ai écrit. Il est spécialement conçu pour fonctionner sur Cygwin à l'aide de la version Cygwin de Perl.

#!/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;
}
0
Lyle Z

Vous pouvez toujours ajouter la bibliothèque de référence à votre projet dans Eclipse puis dans Package Browser, développez simplement les packages dans le fichier JAR jusqu'à ce que vous trouviez la classe recherchée.

0
Das

@ Nikita Rybak: AstroGrep pour Windows est notre ami: http://astrogrep.sourceforge.net/

0
NinjaCat