如果类路径中有两个包含同一类的不同版本的jar,则classpath顺序变得至关重要。
我正在寻找一种工具,可以检测并标记给定类路径或文件夹集中的此类潜在冲突。
当然是一个开始的脚本:
classes=`mktemp`
for i in `find . -name "*.jar"`
do
echo "File: $i" > $classes
jar tf $i > $classes
...
done
有一些聪明的排序/ uniq / diff / grep / awk以后有潜力,但我想知道是否有人知道任何现有的解决方案。
答案 0 :(得分:9)
看起来jarfish会使用“dupes”命令执行您想要的操作。
答案 1 :(得分:6)
JBoss的Tattletale工具是另一个候选人:“如果一个类/包位于多个JAR文件中,则会发现”
答案 2 :(得分:4)
我认为为自己编写工具并不难。
您可以使用System.getProperty(“java.class.path”)获取类路径条目;
然后浏览那里列出的罐子,拉链或目录,收集有关课程的所有信息,找出可能导致问题的那些。
此任务最多需要1或2天。然后,您可以直接在应用程序中加载此类并生成报告。
如果你在一些带有复杂自定义类加载的基础架构中运行,可能java.class.path属性不会显示所有类(例如我曾经看过一个从LDAP加载类的应用程序),但它肯定适用于大多数类案件。
这是一个你可能会觉得有用的工具,我从来没有把它用在我自己身上,但是试一试让我们知道结果。
http://www.jgoodies.com/freeware/jpathreport/features.html
如果您要创建自己的工具,这里是我用于之前发布的相同shell脚本的代码,但是我在Windows机器上使用的代码。当有大量的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 ){}
}
}
}
我希望这会有所帮助。
答案 3 :(得分:3)
Classpath Helper是一个Eclipse插件,有点帮助。
答案 4 :(得分:1)
答案 5 :(得分:1)
如果您不喜欢下载和安装内容,可以使用此一行命令查找与标准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中的所有文件,类文件的greps,找到了dupes,然后greps原始的jar以查看它们出现的位置。使用更复杂的脚本可以提高效率。
答案 6 :(得分:0)
jarclassfinder是另一个eclipse插件选项