¿Existe una herramienta para descubrir si existe la misma clase en varios archivos jar en el classpath?

StackOverflow https://stackoverflow.com/questions/135971

  •  02-07-2019
  •  | 
  •  

Pregunta

Si tienes dos frascos en tu ruta de clase que contienen versiones diferentes de la misma clase, el orden de la ruta de clase se vuelve crítico.

Estoy buscando una herramienta que pueda detectar y marcar dichos conflictos potenciales en una ruta de clase o un conjunto de carpetas.

Ciertamente un script que comienza:

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

con algunos ingeniosos sort / uniq / diff / grep / awk tiene potencial, pero me preguntaba si alguien sabe de alguna solución existente.

¿Fue útil?

Solución

La herramienta Tattletale de JBoss es otro candidato: " Spot si una clase / paquete se encuentra en múltiples archivos JAR "

Otros consejos

Parece que jarfish hará lo que quieras con su " dupes " comando.

Creo que no sería demasiado difícil escribir una herramienta para ti mismo.

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

Y luego recorra los frascos, cremalleras o directorios que se enumeran allí y recopile toda la información sobre las clases y descubra aquellas que puedan 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 se ejecuta en alguna infraestructura con carga de clases personalizadas complejas (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 ser útil, nunca la he usado yo, pero pruébala y déjanos saber el resultado.

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

Si va a crear su propia herramienta, aquí está el código que uso para el mismo script de shell publicado anteriormente, pero que uso en mi máquina con Windows. Se ejecuta más rápido cuando hay toneladas de archivos jar.

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

Hay una clase de Comandos que puedes subclasificar si es necesario, estaba pensando en la opción -execute de " buscar "

Este es mi propio código, por lo que no estaba destinado a estar listo para la producción, solo para hacer 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.

Classpath Helper es un complemento de Eclipse que ayuda un poco.

Si no te gusta descargar e instalar cosas, puedes usar este comando de una línea para encontrar conflictos jar con herramientas gnu estándar. Es rudimentario, pero puedes expandirlo como quieras.

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

(es un poco lento de ejecutar si tienes muchos frascos)

Explicación: Enumera todos los archivos en todos los archivos jar, greps para los archivos de clase, encuentra los dupes y luego toma los archivos originales para ver dónde aparecieron. Podría hacerse más eficiente con un script más complicado.

jarclassfinder es otra opción de complemento de eclipse

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top