16

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?

tomdee
  • 2,319
  • 5
  • 25
  • 39
  • 1
    You'll find no one which also covers runtime dependencies. – BalusC Nov 19 '09 at 14:54
  • You'll not even find a simple one for the other dependencies. Welcome to classpath hell ;) – Andreas Dolk Nov 19 '09 at 15:03
  • For the record: The Class Dependency Analyzer gives the most detailed output, with a nice GUI to examining the results. It is however, quite slow and memory hungry. The Jar Analyzer looks easier to automate as part of a build job and produces lots of useful output. It is also fairly fast. – tomdee Nov 19 '09 at 17:14

6 Answers6

11

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
  • 35,347
  • 40
  • 135
  • 226
  • I may be missing something but I don't see how this will give you a list of useless jars. – Pascal Thivent Nov 19 '09 at 14:42
  • It will tell you which containers your application does depend on, the rest are the useless ones. – sanity Nov 19 '09 at 14:48
  • 1
    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 Dolk Nov 19 '09 at 14:49
  • 1
    That doesn't cover runtime dependencies (i.e. `Class.forName("com.example.Clazz")`. – BalusC Nov 19 '09 at 14:52
  • 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 Nov 19 '09 at 14:56
  • 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 Nov 19 '09 at 14:57
  • seems broken. Just gives error filenotfoundexception: cannot find cda.prefs. Windows 10 – john k Jun 23 '21 at 19:36
9

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.)

Community
  • 1
  • 1
Pascal Thivent
  • 562,542
  • 136
  • 1,062
  • 1,124
5

You also have loosejar.jar which enables you to find the real jar dependencies of your project at runtime !

Anthony O.
  • 22,041
  • 18
  • 107
  • 163
3

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
  • 58,763
  • 21
  • 123
  • 144
2

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

JERiv
  • 554
  • 1
  • 4
  • 8
  • 2
    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 Dolk Nov 19 '09 at 14:59
  • 1
    this has been an Eclipse feature for quite a long time – matt b Nov 19 '09 at 14:59
1

Check Classpath Helper

JuanZe
  • 8,007
  • 44
  • 58