2008-09-25 14 views
17

Si tiene dos jar en su classpath que contienen diferentes versiones de la misma clase, el orden de la classpath se vuelve crítico.¿Hay alguna herramienta para descubrir si existe la misma clase en varios archivos jar en el classpath?

Estoy buscando una herramienta que pueda detectar y señalar esos posibles conflictos en un classpath determinado o un conjunto de carpetas.

Sin duda, una secuencia de comandos que comienza:

classes=`mktemp` 
for i in `find . -name "*.jar"` 
do 
    echo "File: $i" > $classes 
    jar tf $i > $classes 
    ... 
done 

con algún tipo inteligente/Uniq/diferencias/grep/awk más adelante tiene potencial, pero me preguntaba si alguien sabe de alguna solución existentes.

Respuesta

6

La herramienta Tattletale de JBoss es otro candidato: "Puntual si hay una clase/paquete se encuentra en varios archivos JAR"

+0

Pruebe también con jarfish (mi otra respuesta); Lo utilicé con éxito –

+0

¡Sí! O esto o http://stackoverflow.com/questions/135971/is-there-a-tool-to-discover-if-the-same-class-exists-in-multiple-jars-in-the-clas/4516827 # 4516827 debería hacer el truco! –

+0

¿Hay alguna herramienta/forma que filtre solo las clases usadas (importadas)? Tenemos muchas clases duplicadas en nuestro classpath que en realidad nunca se usan –

1
+0

Ambos parecen hacer lo contrario de lo que quiero: encuentran una clase determinada en un conjunto de jarras. Quiero encontrar clases conflictivas en una ruta de clase determinada o conjunto de jarras. –

+0

¿De qué manera es eso lo opuesto? Enumeran los JAR que se pueden encontrar en una clase determinada, y si hay varias coincidencias, los enumeran todos: esa es su lista de conflictos. – skaffman

+0

Pero quiero descubrir cada instancia de alguna clase que aparece en varios contenedores. Tendría que ejecutar whichj para cada clase en mi CLASSPATH y buscar duplicados (sort | uniq | diff) - solo una versión más lenta de mi propuesta de fuerza bruta en la pregunta. –

4

creo que no sería demasiado difícil escribir una herramienta para su auto.

Puede obtener las entradas classpath con System.getProperty ("java.class.path");

Y luego camine por los frascos, cremalleras o directorios allí enumerados y recopile toda la información sobre las clases y descubra las que podrían causar problemas.

Esta tarea tomaría 1 o 2 días como máximo. Luego puede cargar esta clase directamente en su aplicación y generar un informe.

Probablemente la propiedad java.class.path no mostrará todas las clases si ejecuta en alguna infraestructura con carga compleja de clases personalizadas (por ejemplo, una vez vi una aplicación que carga las clases desde el LDAP) pero ciertamente funcionaría para la mayoría de los casos.

Aquí hay una herramienta que puede serle útil, nunca la he usado, pero pruébenos el resultado.

http://www.jgoodies.com/freeware/jpathreport/features.html

Si va a crear su propia herramienta, aquí está el código que utilizo para la misma secuencia de comandos shell publicado antes, pero que yo uso en mi máquina de Windows. Funciona más rápido cuando hay toneladas de archivos jar.

Puede usarlo y modificarlo para que en lugar de caminar recursivamente por un directorio, lea la ruta de la clase y compare el atributo de tiempo de clase.

Hay una clase de comandos que puede subclase si es necesario, estaba pensando en la opción -execute de "encontrar"

Esta mi propio código, por lo que no estaba destinado a ser "listos para la producción", sólo para Haz el trabajo.

import java.io.*; 
import java.util.zip.*; 


public class ListZipContent{ 
    public static void main(String [] args) throws IOException { 
     System.out.println("start " + new java.util.Date()); 
     String pattern = args.length == 1 ? args[0] : "OracleDriver.class";// Guess which class I was looking for :) 
     File file = new File("."); 
     FileFilter fileFilter = new FileFilter(){ 
      public boolean accept(File file){ 
       return file.isDirectory() || file.getName().endsWith("jar"); 
      } 
     }; 
     Command command = new Command(pattern); 
     executeRecursively(command, file, fileFilter); 
     System.out.println("finish " + new java.util.Date()); 
    } 
    private static void executeRecursively(Command command, File dir , FileFilter filter) throws IOException { 
     if(!dir.isDirectory()){ 
      System.out.println("not a directory " + dir); 
      return; 
     } 
     for(File file : dir.listFiles(filter)){ 
      if(file.isDirectory()){ 
       executeRecursively(command,file , filter); 
      }else{ 
       command.executeOn(file); 
      } 
     } 
    } 
} 
class Command { 

    private String pattern; 
    public Command(String pattern){ 
     this.pattern = pattern; 
    } 

    public void executeOn(File file) throws IOException { 
     if(pattern == null) { 
      System.out.println("Pattern is null "); 
      return; 
     } 

     String fileName = file.getName(); 
     boolean jarNameAlreadyPrinted = false; 

     ZipInputStream zis = null; 
     try{ 
      zis = new ZipInputStream(new FileInputStream(file)); 

      ZipEntry ze; 
      while((ze = zis.getNextEntry()) != null) { 
       if(ze.getName().endsWith(pattern)){ 
        if(!jarNameAlreadyPrinted){ 
         System.out.println("Contents of: " + file.getCanonicalPath() ); 
         jarNameAlreadyPrinted = true; 
        } 
        System.out.println(" " + ze.getName()); 
       } 
       zis.closeEntry(); 
      } 
     }finally{ 
      if(zis != null) try { 
       zis.close(); 
      }catch(Throwable t){} 
     } 
    } 
} 

Espero que esto ayude.

+2

¿por qué gastarías 1 o 2 días cuando haya herramientas probables que lo hagan por ti? Si no está trabajando en su proyecto directamente durante 1 o 2 días, es mejor que sea un pasatiempo o que esté haciendo algo mal. – ArtB

+0

El enlace http://www.jgoodies.com/freeware/jpathreport/features.html está muerto. ¿Podrías actualizarlo? –

0

jarclassfinder es otro eclipse opción

+0

La descripción del producto dice que es una "utilidad de complemento para encontrar archivos Java Archive (JAR) que contienen una clase determinada para la ruta de compilación Java de un proyecto". Esto es lo opuesto a lo que necesito. Necesito saber si la misma clase está en dos jarras, NO en qué jar se encuentra una clase dada. –

+1

Detectará que una clase dada se encuentra en varios jar, pero no encontrará todos los casos de clases en varios tarros. –

8

Parece que jarfish va a hacer lo que quiere con su comando "engañados" plugin.

+0

¡Agradable! O esto o http://stackoverflow.com/questions/135971/is-there-a-tool-to-discover-if-the-same-class-exists-in-multiple-jars-in-the-clas/4523559 # 4523559 debería hacer el truco. –

+0

Esto funcionó. No creo que Tattletale maneje muy bien los archivos jar. Si lo hace, no lo resolví. –

0

si no le gusta cómo descargar e instalar cosas que puede utilizar este comando una línea para encontrar los conflictos tarro con herramientas gnu estándar. Es rudimentario, pero puedes ampliarlo como desees.

ls *.jar | xargs -n1 -iFILE unzip -l FILE | grep class | sed "s,.* ,," | tr "/" "." | sort | uniq -d | xargs -n1 -iCLASS grep -l CLASS *.jar | sort -u 

(que es un poco lento para correr si usted tiene una gran cantidad de frascos)

Explicación: En él se enumeran todos los archivos en todos los frascos, GREPS de archivos de clase, encuentra duplicados, entonces GREPS los frascos originales para ver dónde aparecieron. Podría hacerse más eficiente con un script más complicado.

Cuestiones relacionadas