获取一个 jar 的所有导入 类

Getting all imported classes for a jar

对于给定的jar,我想找出这个jar 使用的所有类(尽可能)。因为我有很多罐子,所以我想自动化这个过程。到目前为止我最好的想法是

  1. 反编译jar(我没有这方面的经验,但应该有命令行工具)。
  2. 查找导入并解析它们。

但我希望之前有人做过类似的事情并给我建议。

一种简单的方法是尝试在不添加该 jar 的情况下编译您的代码。

尝试编译并查看编译器错误是最快的方法。

但请记住,class 也可以使用反射(例如通过 spring 配置文件)在运行时加载,并且在没有 jar 的情况下编译代码不会通知您运行时的潜在错误.

使用专门的工具可能是可靠地做到这一点的方法。

但是,一种非常笨拙的方法是获取 JAR 中所有 .class 文件的列表,将 JAR 放在 class 路径上并使用 javap 以获取对其他 classes:

的引用
#!/usr/bin/env bash
javap -cp  -v \
   `zipinfo -1  '*.class' | sed 's:/:.:g' | sed 's:\.class$::'` | \
   grep ' = Class' | sed 's:.*// ::' | sort | uniq

运行 guava-19.0.jar 给出 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"

您将需要更多的输出格式,而且正如其他人所指出的那样,它不会使用任何反射。

这是如何工作的:

zipinfo -1 '*.class' 将打印出 </code> 中所有 <code>.class 文件的名称,这是显示的脚本的参数。 seds 将 /s 更改为 .s 并删除 .class 扩展名,这样你就得到了一个 Java 风格的列表 class 名字。您可以更优雅地执行此操作,但它应该可以工作。

javap 调用将 jar 放在 -cp 的 class 路径上,并传递所有 classes。 -v 使它输出大量信息,包括一些代表对 classes 名称的引用的条目。 grep 确保我们只查看那些,sed 删除了一些我们不感兴趣的额外信息。sort | uniq 确保我们不打印任何 [=45] 的名称=]不止一次。它确实需要更多 sed 来标准化输出格式。