java 是否有工具可以发现类路径中的多个 jar 中是否存在同一个类?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/135971/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 11:09:12  来源:igfitidea点击:

Is there a tool to discover if the same class exists in multiple jars in the classpath?

javajarclasspath

提问by David Citron

If you have two jars in your classpath that contain different versions of the same class, the classpath order becomes critical.

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

I am looking for a tool that can detect and flag such potential conflicts in a given classpath or set of folders.

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

Certainly a script that starts:

当然是一个开始的脚本:

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

with some clever sort/uniq/diff/grep/awk later on has potential, but I was wondering if anyone knows of any existing solutions.

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

采纳答案by Zac Thompson

The Tattletaletool from JBoss is another candidate: "Spot if a class/package is located in multiple JAR files"

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

回答by Zac Thompson

Looks like jarfishwill do what you want with its "dupes" command.

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

回答by OscarRyz

I think it wouldn't be too hard to write a tool for your self.

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

You can get the classpath entries with System.getProperty("java.class.path");

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

And then walk through the jars, zips, or directories listed there and collect all the information about the classes and findout those that might cause trouble.

然后遍历其中列出的 jar、zip 或目录,收集有关类的所有信息并找出可能导致问题的信息。

This task would take 1 or 2 days at most. Then you can load this class directly in your application and generate a report.

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

Probably java.class.path property wont's show all the classes if you run in some infrastructure with complex custom class loading ( for instance I once saw an app that load the classes from the LDAP ) but it would certainly work for most of the cases.

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

Heres a tool you might find useful, I've never use it my self, but give it a try and let us know the result.

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

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

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

If you are going to create your own tool, here is the code I use for the same shell script posted before, but that I use on my Windows machine. It runs faster when there are tons of jar files.

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

You can use it and modify it so instead of recursively walk a directory, read the class path and compare the .class time attribute.

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

There is a Command class you can subclass if needed, I was thinking in the -execute option of "find"

有一个命令类,您可以根据需要对其进行子类化,我在考虑“查找”的 -execute 选项

This my own code, so it was not intended to be "production ready", just to do the work.

这是我自己的代码,所以它不打算“生产就绪”,只是为了完成工作。

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

I hope this helps.

我希望这有帮助。

回答by ferbs

Classpath Helperis an Eclipse plug-in that helps a little bit.

Classpath Helper是一个 Eclipse 插件,可以提供一点帮助。

回答by Chris Seline

If you dislike downloading and installing stuff you can use this one line command to find jar conflicts with standard gnu tools. It is rudimentary but you can expand it as you will.

如果你不喜欢下载和安装东西,你可以使用这一行命令来查找与标准 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

(it is a bit slow to run if you have a lot of jars)

(jar多的话跑起来有点慢)

Explanation: It lists all the files in all the jars, greps for class files, finds dupes, then greps the original jars to see where they appeared. It could be made more efficient with a more complicated script.

解释:它列出所有 jars 中的所有文件,greps 类文件,找到 dupes,然后 grep 原始 jars 以查看它们出现的位置。使用更复杂的脚本可以提高效率。

回答by s_t_e_v_e

jarclassfinderis another eclipse plugin option

jarclassfinder是另一个 Eclipse 插件选项