tags:

views:

252

answers:

5

I'm currently passing a very large classpath to javac to compile a java project.

I know that a number of those jar files aren't needed.

Is there a simple way of finding out which files aren't needed?

+4  A: 

I guess that "remove them one by one and check if the application still compiles and works" is not the expected answer :)


(EDIT: While the approach suggested above can be a bit automated, it remains somehow painfull and there must be an alternative, at least for compile-time dependencies. After some googling, I found Jar Analyzer which seems to be a nice tool for this work as explained in this blog post:

Jar Analyzer scans for compile dependencies, meaning that it can create a tree of which JAR-files are needed to compile which JAR-files that are needed to compile these JAR-files, and so on. You get a very nice report/graph which shows you all the JAR-files and why they are in there.

You can also see the JAR-files that don't have any connection to your code, remove them and their children. What I found in our libs folder was that about 20% of the 150 JAR files in our libs folder were unused at compile time, and these were potential JARs to be removed.

The big aber is that you don't get any hint on which JAR-files are used only at runtime by means of discovery and reflection. And this is where the real work begins.

The only way to find out whether a JAR file is used at runtime is basically to take it out, start up your application and test every functionality. If you have an application of moderate size, performing a 100% regression test takes many hours. So in practice, I ended up doing alot of guessing, quick and dirty testing, and asking around to find out which of the runtime dependencies were actually in use.

It seems pretty easy to use: download, unzip and run the tool on a directory containing all jars. Or use the provided Ant task.)

Pascal Thivent
I was hoping for something a little less manual!
tomdee
You always can implement some script.
Mykola Golubyev
This is however most probably the best way if you want to cover runtime dependencies as well.
BalusC
Strike - 100% candidate for accepted answer, as if they quickly developed something to solve tomdee's problem ;-)
Andreas_D
+5  A: 

You need the Class Dependency Analyzer tool. To quote the introduction:

The purpose of this tool is to analyze Java™ class files in order to learn more about the dependencies between those classes.

True, it won't catch runtime dependencies - but short of running an exhaustive 100% coverage test suite you can never be sure you've caught all runtime dependencies.

If you expect runtime dependencies you should use the CDA as a first-pass, then do exhaustive testing of the resultant app to ensure that there are no jar files which were only referenced through runtime dependencies.

sanity
I may be missing something but I don't see how this will give you a list of useless jars.
Pascal Thivent
It will tell you which containers your application does depend on, the rest are the useless ones.
sanity
Correct - you could compare the used jars with the classpath, but that's risky - a library may not have been used at the time you analyze the path but be necessary aswell..
Andreas_D
That doesn't cover runtime dependencies (i.e. `Class.forName("com.example.Clazz")`.
BalusC
Also doesn't help with reflection, code that uses ServiceLocator, etc. If you have tests, I'd just start removing stuff manually until the tests break. If you have no tests, then Java's lazy class-loading is going to make things difficult for you.
Dave Ray
TO put it another way, the run-time classpath is just as important, if not more, than the classpath you give to javac.
Dave Ray
@sanity Of course! Thanks for the answer.
Pascal Thivent
+1  A: 

The latest build of eclipse will warn you about unused imports in your source code

JERiv
If you really mean the import statement in a java source file - eclipse warnings are pretty old. And it's the other way round - he's looking for classpath entries that are not used.
Andreas_D
this has been an Eclipse feature for quite a long time
matt b
+2  A: 

The compiler has a -verbose option, and it is quite verbose. It informs of each class that gets loaded and where it is loaded from!

While it's not quite user-friendly and it doesn't provide high-level analysis, I found it very useful for debugging classpath conflicts. This tells you the jars that get used (with help of grep), not the ones that don't get used.

notnoop
+1  A: 

Check Classpath Helper

JuanZe