views:

246

answers:

5

In our application through the process of developing a lot of JAR files has been collected. How can I filter out those, which are not used by application anymore? On some easy way?

A: 

Write a script which removes them one by one from your build path, compiles the project and checks for build errors. The script would assemble a list of unused jars. Should be easy to write in bash/python.

This solution cannot track runtime dependencies based on reflection (see my comment below).

pajton
That will find compile-time errors, but not errors that result at runtime from failures of delayed class loading. Especially with complex frameworks such things are quite common. Even worse is when the framework picks one available class for a specified interface, and the behaviour is subtly different depending on which implementation is actually used. I strongly recommend running a full integration test after you think you are done.
Kilian Foth
You are right, this solution doesn't handle that case. But I think it is quite impossible to do that automatically if you use some advanced reflection. What would you do, extract all the strings in the code that may be matching a class name:>?
pajton
You can also do this via the Eclipse IDE by removing items from the .classpath one at a time and rebuilding the project. When stuff turns red you removed one that's in use. ;-)
Chris Nava
+1  A: 

if youre using maven, there's a mojo for that : mvn dependency:analyze if not, i dont know of any easy way. the hard way would involve bytecode analysis of all the compiled classes of your project to inspect imports ...

hatchetman82
and come to think of it, even that wont catch reflection ...
hatchetman82
No... But maven will catch dependencies declared in the pom.xml but not obvious in the code (frameworks and dynamically loaded drivers for example.)
Chris Nava
A: 

Maybe you could write your own ClassLoader, inheriting from java.lang.ClassLoader, that logs the paths of loaded classes? That still doesn't solve the problem of ensuring full coverage of all classes loaded during all possible code paths, though

Max
+3  A: 

If you are sure your you can exercise your application so that it uses all it's jars, you can create a simple perl script:

while (<>) {
    $l{$1}++ if m/\s+from\s+(.+\.jar)/;
}

for $l (keys(%l)) {
    print "$l\n";
}

(lets name it list_jars.pl) and feed it the output of a verbose run:

java -verbose -jar YOUR_APP.jar | perl list_jars.pl

which should list all sources of classes loaded.

rsp
now that is a really neat trick
hatchetman82
What if I have web application archive (war)?
Trick
The perl script parses the verbose classloader output, for a web-app you should be able to add -verbose to the startup parameters and parse the resulting standard output logging. (This will probably show jars that are used by the servlet container too.)
rsp
It was a challenge, but it worked.
Trick
+1  A: 

I've used stan. it's a structure analyzer for java, and it gave me very good results.

You can visually see which jar are used and which not.

volothamp