Есть ли инструмент, позволяющий определить, существует ли один и тот же класс в нескольких банках в пути к классам?
Вопрос
Если в вашем пути к классам есть два jar-файла, которые содержат разные версии одного и того же класса, порядок путей к классам становится критическим.
Я ищу инструмент, который может обнаруживать и отмечать такие потенциальные конфликты в заданном пути к классам или наборе папок.
Конечно скрипт, который запускается:
classes=`mktemp`
for i in `find . -name "*.jar"`
do
echo "File: $i" > $classes
jar tf $i > $classes
...
done
с некоторой умной сортировкой sort/uniq/diff/grep/awk позже есть потенциал, но мне было интересно, знает ли кто-нибудь о каких-либо существующих решениях.
Решение
А Сплетница инструмент от JBoss — еще один кандидат:«Определите, находится ли класс/пакет в нескольких файлах JAR»
Другие советы
Выглядит как рыба-кувшин будет делать то, что вы хотите, с помощью своей команды «dupes».
Я думаю, что было бы не так уж сложно написать инструмент для себя.
Вы можете получить записи пути к классам с помощью System.getProperty("java.class.path");
А затем пройдитесь по перечисленным там jar-файлам, zip-файлам или каталогам, соберите всю информацию о классах и найдите те, которые могут вызвать проблемы.
Эта задача займет максимум 1-2 дня.Затем вы можете загрузить этот класс прямо в свое приложение и создать отчет.
Вероятно, свойство java.class.path не будет отображать все классы, если вы работаете в некоторой инфраструктуре со сложной загрузкой пользовательских классов (например, однажды я видел приложение, которое загружает классы из LDAP), но в большинстве случаев это, безусловно, будет работать.
Вот инструмент, который может оказаться вам полезным. Я никогда не использовал его сам, но попробуйте и сообщите нам о результате.
http://www.jgoodies.com/freeware/jpathreport/features.html
Если вы собираетесь создать свой собственный инструмент, вот код, который я использую для того же сценария оболочки, опубликованного ранее, но который я использую на своем компьютере с Windows.Он работает быстрее, когда имеется множество файлов jar.
Вы можете использовать его и изменить, чтобы вместо рекурсивного обхода каталога читать путь к классу и сравнивать атрибут времени .class.
Существует класс Command, который вы можете при необходимости подклассифицировать, я думал об опции -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 ){}
}
}
}
Надеюсь, это поможет.
Помощник пути к классам это плагин Eclipse, который немного помогает.
Если вам не нравится загружать и устанавливать что-то, вы можете использовать эту однострочную команду, чтобы найти конфликты jar со стандартными инструментами GNU.Он элементарный, но вы можете расширить его по своему усмотрению.
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-файлы, чтобы увидеть, где они появились.Его можно было бы сделать более эффективным с помощью более сложного сценария.
jarclassfinder это еще один вариант плагина eclipse