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.