クラスパス内の複数のjarに同じクラスが存在するかどうかを検出するツールはありますか?
質問
同じクラスの異なるバージョンを含む2つの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の Tattletale ツールは別の候補です。クラス/パッケージが複数のJARファイル"
他のヒント
jarfish のように見えると、" 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 time属性を比較するために、これを使用して変更できます。
必要に応じてサブクラス化できる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 ){}
}
}
}
これが役立つことを願っています。
Classpath Helper は、少し役立つEclipseプラグインです。
もののダウンロードとインストールを嫌う場合は、この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がたくさんある場合、実行に少し時間がかかります)
説明: すべてのjar内のすべてのファイルをリストし、クラスファイルを検索し、重複を見つけ、元のjarを検索して、それらが出現した場所を確認します。より複雑なスクリプトでより効率的にすることができます。
jarclassfinder は別のEclipseプラグインオプションです