简体   繁体   English

获取罐子的所有导入类

[英]Getting all imported classes for a jar

For a given jar, I want to find out all classes (as far as possible) that are used by this jar. 对于给定的jar,我想找出该jar使用的所有类(尽可能)。 Since I have a lot of jars, I want to automate this process. 由于我有很多罐子,因此我想使这一过程自动化。 My best idea so far is to 到目前为止,我最好的主意是

  1. Decompile the jar (I have no experience with that but there should be command line tools). 反编译jar(我没有经验,但是应该有命令行工具)。
  2. Look for imports and parse them. 寻找导入并解析它们。

But I hope that someone else has done something like this before and give me advice on this. 但是我希望其他人以前做过这样的事情,并就此给我建议。

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: 但是,这样做的一种真正麻烦的方法是获取JAR中所有.class文件的列表,将JAR放在类路径中,并使用javap获取对其他类的引用:

#!/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 : guava-19.0.jar上运行此guava-19.0.jar可得到以下效果

"[[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. zipinfo -1 $1 '*.class'将打印$1中所有.class文件的名称,这是所示脚本的参数。 The sed s change / s to . sed更迭/ s到. s and remove the .class extension, so that you end up with a list of Java-style class names. 并删除.class扩展名,以便最终获得Java样式的类名列表。 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. javap调用使用-cp将jar放在类路径中,并传递所有类。 -v makes it output a lot of information, including some entries which represent references to names of classes. -v使它输出大量信息,包括一些表示对类名称的引用的条目。 The grep ensures we're only looking at those, the sed removes some extra information we're not interested in. sort | uniq grep保证我们只是看着那些中, sed删除我们不感兴趣,一些额外的信息。 sort | uniq sort | uniq ensures we're not printing the name of any class more than once. sort | uniq确保我们不会多次打印任何类的名称。 It does need a bit more sed ding to standardize an output format. 它需要更多的sed丁标准化的输出格式。

A simple way is to try to compile your code without adding that jar. 一种简单的方法是尝试在不添加该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. 但是请记住,也可以使用反射(例如,通过spring配置文件)在运行时加载类,并且在不使用jar的情况下编译代码不会通知您运行时的潜在错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM