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");
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.
This task would take 1 or 2 days at most. Then you can load this class directly in your application and generate a report.
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.
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
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.
You can use it and modify it so instead of recursively walk a directory, read the class path and compare the .class time attribute.
There is a Command class you can subclass if needed, I was thinking in the -execute option of "find"
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.