2010-08-16 1 views
25

Qual è il tuo strumento preferito, plugin, script, per trovare una classe java in un gruppo di file jar?come trovare il file jar contenente una definizione di classe?

Molto spesso eredito codice che si lamenta di una classe che non esiste ed è solo perché il file jar non è incluso nel classpath. Ma in che file jar è la classe? Potrei non avere il JAR (quindi devo cercare online), o l'aggiunta di un JAR al classpath potrebbe creare un problema di definizione della classe duplicato.

Ovviamente preferirei un plug-in di eclissi, ma sono aperto a qualsiasi software che funzioni con Windows.

Lo so ... Windows non è la mia scelta, ma è quello con cui ho avuto modo di lavorare.

Grazie!

Luis

P.S. Grazie per le tue risposte. Dopo aver esaminato alcune risposte, mi sono reso conto che avrei dovuto spiegare meglio il mio scenario. Avevamo una libreria di file JAR scaricati o creati, ma a volte la classe sarebbe online da qualche parte.

+0

ottima domanda. Mi imbatto sempre in questo Non so perché fosse chiuso come fuori tema. strano – Tagar

risposta

5

Di solito uso bash per questo: grep -lr "ClassName" . Il trucco è che i nomi non sono codificati in alcun modo. Puoi aprire il file jar nell'editor di testo e li vedrai. (Puoi anche includere il nome del pacchetto nella query di ricerca.)

Sospetto, ci sono anche alcune finestre equivalenti.

+0

Sì, ma il problema è che è difficile dire se il file contiene una definizione o un uso della classe. E, sì, c'è un'utilità grep che può essere scaricata. Grazie! – luiscolorado

+0

@luiscolorado Non mi ha mai dato un falso positivo prima. Non lo so, probabilmente la maggior parte del contenuto (incluse le classi di riferimento) è codificata in qualche modo. –

+0

Mmmmmh ... Sfortunatamente ho ricevuto un mucchio di falsi positivi. O forse è perché la classe ha lo stesso nome su più pacchetti. In ogni caso, darò un altro colpo. Grazie, Nikita! – luiscolorado

0

È sempre possibile aggiungere la libreria di riferimento al progetto in Eclipse e quindi in Package Browser, basta espandere i pacchetti nel file JAR fino a trovare la classe che si sta cercando.

+0

Certamente! Sebbene stavo cercando qualcosa di più veloce :) Devo avere in lista 20 file jar in questo progetto, e chissà quante classi. – luiscolorado

+1

Per i jar sul percorso di build, basta usare Ctrl-Shift-T per individuare una classe. –

+0

Ancora non la mia tazza di tè, ma vedremo. – luiscolorado

0

@Nikita Rybak: AstroGrep per Windows è il nostro amico: http://astrogrep.sourceforge.net/

+0

Mi è piaciuto AstroGrep! L'ho trovato amichevole rispetto alla versione da riga di comando. Tuttavia, ha lo stesso problema di qualsiasi grep (vedi il mio commento a Nikita Rybak). – luiscolorado

+0

Vero ... _but_ con AstroGrep è possibile impostarlo per restituire +/- N numero di righe. Quindi non è l'opzione migliore, ma potrebbe funzionare. – NinjaCat

1

Molto spesso mi ereditare il codice che si lamenta di una classe che non esiste, ed è solo perché il file jar non è incluso nel il classpath.

Se non è nel classpath, probabilmente non si dispone del file JAR stesso. La ricerca tramite la funzione incorporata di Eclipse Ctrl+Shift+T non sarà di grande aiuto. Di solito è possibile utilizzare il nome del pacchetto per "indovinare" dove è possibile ottenere il file JAR da Internet. Per esempio. una classe org.apache.commons.lang.XXX è disponibile allo http://commons.apache.org/lang.

Per i non udenti, io stesso uso http://grepcode.com, il motore di ricerca del codice sorgente JAR.

+1

_Se non si trova nel classpath, probabilmente non si ha affatto il file JAR_ Bene, mi è capitato spesso con jboss. Centinaia di librerie interne e spesso ne hai bisogno di poche per compilare il tuo codice. Grazie per il collegamento, però, è interessante. –

+0

@Nikita: In questo caso specifico, preferisci aggiornare il server di destinazione del tuo progetto web dinamico a JBoss. – BalusC

+0

Boo ... ancora non disponibile 8 anni dopo! Penso che Maven Repo dovrebbe offrire questo ... ha tutte le cose ... "tutto" che deve fare è tenere un indice Lucene aggiornato, sì, OGNI singola classe in tutti i suoi .jars! –

1

uso questo:

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

Nelle stesse linee come la risposta di BalusC (non posso postare commenti ancora né collegamento 2 gli URL, senza reputazione :(), è possibile trovare un vaso grazie a questi 2 vaso motori finder: - http://www.jarfinder.com/ - findjar

+1

jarfinder * IS * tuo amico. – Tom

+0

Il sito Web è stato spostato su: http://www.findjar.com/ –

2

ho scritto un programma per questo: https://github.com/javalite/jar-explorer sarà anche decompilare il codice byte esistente visualizzare le interfacce, metodi, classi super mostreranno contenuti di altre risorse - testo, immagini, html, ecc.

+0

grazie !! ottimo strumento !!! – DBQ

6

Ho incontrato lo stesso problema innumerevoli volte, quindi ho scritto un piccolo strumento per trovarli.

Una semplice riga di comando: findclass MyClass -classpath ...

Si cerca le directory, jar, zip, la guerra e file per le orecchie per la classe. L'ho scritto qualche anno fa e lo uso sempre. Ho pensato che anche altri lo trovassero utile quindi ho caricato su github.

E 'disponibile gratuitamente per il download: https://github.com/eurozulu/Findclass/tree/master/dist

Se si vuole guardare il sorgente, che è nello stesso sito: https://github.com/eurozulu/Findclass/tree/master

Se ti piace, fammelo sapere per dare me che sentirsi a proprio agio :)

+0

Ho trovato utile il tuo strumento. Grazie! – ObviousChild

2

Io uso jarscan. È un file jar eseguibile che può cercare in modo ricorsivo un'intera struttura di cartelle per i jar che contengono la classe che si sta cercando. Cerca per nome classe, nome pacchetto o regex.

33

(si tratta di un miglioramento rispetto la sceneggiatura che avevo in versioni precedenti di risposta in quanto produce in uscita molto più pulito al prezzo di qualche awk speciale/brutto citando.)

ho costruito uno script (findinjars) che fa proprio questo.

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

si può quindi richiamare con:

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

o semplicemente

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

caratteri punto nel nome completo della classe saranno interpretate alla regexp senso di 'carattere' ma questo non è un grosso problema dal momento che questa è un'utilità euristica (ecco perché è case-insensitive anche BTW). Di solito non mi preoccupo del nome completo della classe e ne scrivo solo una parte.

2

Grepj è un'utilità della riga di comando per cercare le classi all'interno dei file jar.

È possibile eseguire il programma di utilità come grepj package.Class my1.jar my2.war my3.ear

Ambito di ricerca è

  • classi nel file jar
  • Classi all'interno di manufatti annidate come vasi all'interno di file EAR e WAR
  • WEB-INF/anche le classi vengono cercate.

Possono essere forniti file di vasi, orecchie e guerra multipli.

-1

Volevo solo ricordare qui che terzi si crea possono essere cercati per qualche nome di file specifico in jarfinder Anche se non risponde direttamente alla domanda, ma non sarà male :)

Spero che questo aiuti

+0

Questa è essenzialmente una risposta a un collegamento. Inoltre, il link che è stato già fornito, ed è, di fatto, la risposta più votata. Sei stato condannato a morte da * tre anni * –

3

Un comando più semplice.Non è necessario utilizzare 'while-do', utilizzare '& &' per stampare il nome del file se 'grep' trova la classe.

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

for x in $ (trovare -name '* .jar'.) do decomprimere -l $ x | grep WCCResponseImpl done

0

Ho provato alcuni di questi comandi Unix, ma hanno commesso errori per vari motivi. Ecco uno script Perl che ho scritto. È progettato specificamente per funzionare su Cygwin usando la versione Cygwin di 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; 
} 
1

Il modo migliore e più semplice è utilizzare il decompilatore JAD. E sì, è un ECLIPSE PLUGIN!

Download e salvare il plug-in in qualsiasi posizione sul computer.

Il plugin contiene i seguenti file:

  1. Una cartella Temp
  2. Un file di jad.exe
  3. A * * net.sf.jadclipse_3.3.0.jar JAR plug
  4. Un file Leggimi

Effettuare le seguenti operazioni :

  1. Copia il plugin JAR alla cartella plugins della cartella di Eclipse
  2. Aprire Eclipse. Vai a Finestra >> Preferenze >> Java >> JADClipse >> Percorso a Decompiler.
  3. dare il percorso di jad.exe
  4. riavviare Eclipse

Ora selezionare qualsiasi classe e premere F3.

Il file .class verrà decompilato automaticamente e visualizzerà il contenuto!

0

Ho recentemente creato uno strumento per cercare classi, pacchetti e librerie. Puoi provarlo con lo http://javasearch.buggybread.com/. Clicca sul framework e ti aiuterà a localizzare le informazioni di dipendenza (jar, pom).