在类路径中是否存在一个工具,可以发现同一类是否存在于多个JAR包中?

23

如果您的类路径中有两个包含相同类不同版本的容器,那么类路径顺序就变得至关重要。

我正在寻找一种能够检测并标记给定类路径或文件夹集中这种潜在冲突的工具。

当然,可以编写一个脚本来启动:

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

使用一些巧妙的sort/uniq/diff/grep/awk之后,可能会有潜力,但我想知道是否有任何现有的解决方案。


1
可能是如何检测类路径中的重复JAR?的重复内容。 - vorburger
6个回答

9

看起来jarfish的“dupes”命令可以满足您的需求。


不错!这个或者https://dev59.com/rnVC5IYBdhLWcg3w9GHM#4523559应该都可以解决问题。 - David Citron
这个可行。我不认为Tattletale对jar文件的处理很好。如果它可以,那我没弄清楚。 - Janus Troelsen

8

Tattletale 工具来自 JBoss,是另一个备选项:“检测类/包是否位于多个 JAR 文件中”。


也可以尝试一下jarfish(我的另一个答案);我曾经成功地使用过它。 - Zac Thompson
是的!这个或者https://dev59.com/rnVC5IYBdhLWcg3w9GHM#4516827应该可以解决问题! - David Citron
有没有一种工具/方法可以过滤掉只使用(导入)的类? 我们的类路径中有很多重复的类,实际上从未被使用。 - Sebastian Saip

3

如果您不喜欢下载和安装软件,可以使用这个一行命令来查找与标准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包,运行速度会有点慢)

解释: 它列出了所有JAR包中的文件,查找类文件的重复项,然后在原始JAR包中查找它们出现的位置。使用更复杂的脚本可以使其更有效率。


3

Classpath Helper 是一款帮助 Eclipse 的插件,它可以提供一些帮助。


3
我认为为自己编写一个工具并不难。
您可以使用System.getProperty("java.class.path")获取类路径条目。
然后遍历列出的jar、zip或目录,并收集有关类的所有信息,找出可能会引起麻烦的类。
这项任务最多需要1到2天时间。然后,您可以直接在应用程序中加载此类并生成报告。
可能java.class.path属性无法显示所有类,如果在一些具有复杂自定义类加载的基础设施中运行(例如,我曾经看到过一个从LDAP加载类的应用程序),但它肯定适用于大多数情况。
这是一个您可能会发现有用的工具,我自己从未使用过,但请尝试并告诉我们结果。

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

如果您想创建自己的工具,以下是我在Windows机器上使用的相同shell脚本代码,但当有大量jar文件时运行速度更快。您可以使用并修改它,以便不再递归地遍历目录,而是读取类路径并比较.class时间属性。如果需要,可以子类化Command类,我正在考虑“find”选项的-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 ){}
        }
    }
}

我希望这可以帮到你。


2
为什么要花费1或2天的时间,当可能有工具可以为您完成它?如果您在1或2天内没有直接为项目工作,那么最好是一种爱好,否则您可能做错了什么。 - Sled
链接http://www.jgoodies.com/freeware/jpathreport/features.html已失效,请更新一下,谢谢。 - Gábor Lipták
JPathReport似乎已经很久没有更新了,但我找到了这个镜像网站:https://web.archive.org/web/20120209215148/http://www.jgoodies.com/freeware/jpathreport/features.html,以及这个下载页面:https://web.archive.org/web/20080626003101/http://www.jgoodies.com:80/downloads/index.html。 - seanf

0

该产品的描述称它是一个"插件实用程序,用于查找包含项目Java构建路径中给定类的Java存档(JAR)文件。"这正好与我所需相反。我需要知道同一类是否在两个JAR文件中,而不是特定类位于哪个JAR文件中。 - David Citron
1
它将检测到给定类在多个JAR文件中的情况,但不会找到所有存在于多个JAR文件中的类。 - s_t_e_v_e

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接