【问题标题】:Is there a tool to discover if the same class exists in multiple jars in the classpath?是否有工具可以发现类路径中的多个 jar 中是否存在同一个类?
【发布时间】:2010-09-13 06:04:20
【问题描述】:

如果您的类路径中有两个 jar 包含同一类的不同版本,则类路径顺序变得至关重要。

我正在寻找一种工具,可以检测和标记给定类路径或一组文件夹中的此类潜在冲突。

当然是启动脚本:

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

稍后使用一些聪明的 sort/uniq/diff/grep/awk 有潜力,但我想知道是否有人知道任何现有的解决方案。

【问题讨论】:

标签: java jar classpath


【解决方案1】:

看起来jarfish 会用它的“dupes”命令做你想做的事。

【讨论】:

  • 不错!这个或stackoverflow.com/questions/135971/… 应该可以解决问题。
  • 这行得通。我认为 Tattletale 不能很好地处理 jar 文件。如果是这样,我没弄明白。
【解决方案2】:

来自 JBoss 的 Tattletale 工具是另一个候选者:“发现一个类/包是否位于多个 JAR 文件中”

【讨论】:

  • 也试试 jarfish(我的另一个答案);我用成功了
  • 是的!这个或stackoverflow.com/questions/135971/… 都可以解决问题!
  • 是否有过滤只使用(导入)类的工具/方式?我们的类路径中有很多实际上从未使用过的重复类
【解决方案3】:

我认为为自己编写一个工具不会太难。

您可以使用 System.getProperty("java.class.path"); 获取类路径条目

然后遍历那里列出的 jars、zip 或目录,并收集有关这些类的所有信息,并找出可能导致麻烦的那些。

此任务最多需要 1 或 2 天。然后你可以直接在你的应用程序中加载这个类并生成一个报告。

如果您在某些具有复杂自定义类加载的基础架构中运行(例如,我曾经看到一个从 LDAP 加载类的应用程序),那么 java.class.path 属性可能不会显示所有类,但它肯定适用于大多数情况案例。

这是一个您可能会觉得有用的工具,我自己从未使用过,但请尝试一下,让我们知道结果。

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

如果您要创建自己的工具,这里是我用于之前发布的相同 shell 脚本的代码,但我在我的 Windows 机器上使用。当有大量 jar 文件时,它运行得更快。

您可以使用它并对其进行修改,而不是递归地遍历目录,读取类路径并比较 .class 时间属性。

有一个命令类,如果需要,您可以子类化,我正在考虑“查找”的 -execute 选项

这是我自己的代码,所以它不是为了“准备好生产”,只是为了完成工作。

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 ){}
        }
    }
}

我希望这会有所帮助。

【讨论】:

【解决方案4】:

Classpath Helper 是一个 Eclipse 插件,有点帮助。

【讨论】:

    【解决方案5】:

    如果您不喜欢下载和安装东西,您可以使用这一行命令来查找与标准 gnu 工具的 jar 冲突。它很简陋,但您可以随意扩展它。

    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
    

    (如果你有很多jar,运行会有点慢)

    说明: 它列出了所有 jars 中的所有文件,对类文件进行 greps,查找骗子,然后对原始 jars 进行 greps 以查看它们出现的位置。使用更复杂的脚本可以提高效率。

    【讨论】:

      【解决方案6】:

      jarclassfinder 是另一个 Eclipse 插件选项

      【讨论】:

      • 该产品的描述说它是一个“用于查找包含项目 Java 构建路径的给定类的 Java 归档 (JAR) 文件的插件实用程序”。这与我需要的相反。我需要知道同一个类是否在两个 jar 中,而不是给定类在哪个 jar 中。
      • 它会检测到一个给定的类在多个jar中,但它不会找到多个jar中的所有类。
      猜你喜欢
      • 2014-05-25
      • 1970-01-01
      • 2011-04-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多