Reputation: 35843
For a given jar, I want to find out all classes (as far as possible) that are used by this jar. Since I have a lot of jars, I want to automate this process. My best idea so far is to
But I hope that someone else has done something like this before and give me advice on this.
Upvotes: 1
Views: 2192
Reputation: 18633
Using a specialised tool is probably the way to do this reliably.
However, one really janky way of doing this would be to grab a list of all the .class
files in your JAR, put the JAR on the classpath and use javap
to get references to other classes:
#!/usr/bin/env bash
javap -cp $1 -v \
`zipinfo -1 $1 '*.class' | sed 's:/:.:g' | sed 's:\.class$::'` | \
grep ' = Class' | sed 's:.*// ::' | sort | uniq
Running this on guava-19.0.jar
gives this:
"[[B"
"[B"
"[[C"
"[C"
com/google/common/annotations/Beta
com/google/common/annotations/GwtCompatible
com/google/common/annotations/GwtIncompatible
com/google/common/annotations/VisibleForTesting
com/google/common/base/Absent
com/google/common/base/AbstractIterator
...............................................................
"[Lcom/google/common/util/concurrent/MoreExecutors$DirectExecutor;"
"[Lcom/google/common/util/concurrent/Service$State;"
"[Lcom/google/thirdparty/publicsuffix/PublicSuffixType;"
"[Ljava/io/File;"
"[[Ljava/lang/annotation/Annotation;"
"[Ljava/lang/annotation/Annotation;"
"[Ljava/lang/Class;"
"[Ljava/lang/Comparable;"
"[Ljava/lang/Enum;"
"[[Ljava/lang/Object;"
"[Ljava/lang/Object;"
"[Ljava/lang/reflect/Field;"
"[Ljava/lang/reflect/Method;"
"[Ljava/lang/reflect/Type;"
"[Ljava/lang/reflect/TypeVariable;"
"[Ljava/lang/StackTraceElement;"
"[Ljava/lang/String;"
"[Ljava/net/URL;"
"[Ljava/util/Iterator;"
"[Ljava/util/Map$Entry;"
"[[S"
"[S"
sun/misc/Unsafe
"[[Z"
"[Z"
You'll need more output formatting, and, as others have pointed out, it won't pick up any use of reflection.
How this works:
zipinfo -1 $1 '*.class'
will print out the names of all .class
files in $1
, which is the argument to the script shown. The sed
s change /
s to .
s and remove the .class
extension, so that you end up with a list of Java-style class names. You could do this more elegantly, but it should work.
The javap
invocation puts the jar on the classpath with -cp
, and passes all the classes. -v
makes it output a lot of information, including some entries which represent references to names of classes. The grep
ensures we're only looking at those, the sed
removes some extra information we're not interested in. sort | uniq
ensures we're not printing the name of any class more than once. It does need a bit more sed
ding to standardize an output format.
Upvotes: 6
Reputation: 26946
A simple way is to try to compile your code without adding that jar.
Try to compile and looking at the compiler errors is the fastest way to do that.
But remember that a class can be loaded also a runtime using reflection (for example via spring configuration files) and compiling the code without the jar will not inform you about potential errors at runtime.
Upvotes: 0