1

I need to analyse which classes are used (referenced) by the different .class files in a jar. I know that

jdeps -v example.jar

produces this output. Unfortunately, I need a solution that works if the user has only a JDK 1.7. How could this be achieved?

J Fabian Meier
  • 33,516
  • 10
  • 64
  • 142
  • I guess technically you could do that using `javap -v` or `-c`, but requiring a JDK8 seems like the sane option – Aaron Feb 10 '17 at 10:29
  • Have a look to the answers in following thread https://stackoverflow.com/questions/4326407/analyze-jar-dependencies-in-a-java-project – SubOptimal Feb 10 '17 at 10:37
  • @Aaron The users of the program are the developers in our company, which does not use Java 8. I cannot do anything about this. – J Fabian Meier Feb 10 '17 at 10:47
  • @JFMeier I don't think they need to use it, just have an install available so they can run `jdeps`. However I'm not sure `jdeps` can inspect classes from earlier versions. Anyway I guess the question SubOptimal linked should provide you with solutions – Aaron Feb 10 '17 at 11:24
  • Maybe I can put it on a network drive and call it. It probably does not rely on environment variables. – J Fabian Meier Feb 10 '17 at 11:48

3 Answers3

2

I've been able to obtain seemingly good results with javap -c and a regex filter.

I used cygwin to obtain my results, but you should be able to do this in any environment, all you need is a tool to unzip, javap and a tool to execute regular expressions. In current Windows versions, powershell would provide those features.

The following code will list the classes referenced by each class inside a jar file :

mkdir workDir
unzip yourJar.jar -d workDir
shopt -s globstar
for classFile in **/*.class; do
    echo "Classes used in $classFile :"
    javap -c "$classFile" | grep -Eo "([a-zA-Z0-9]+/)+[A-Z][a-zA-Z0-9]*" | sort -u
    echo
done

You said you wanted the classes referenced in a jar file, so assuming you don't want the detail of each class this should work :

mkdir workDir
unzip yourJar.jar -d workDir
shopt -s globstar
for classFile in **/*.class; do
    javap -c "$classFile" | grep -Eo "([a-zA-Z0-9]+/)+[A-Z][a-zA-Z0-9]*" 
done | sort -u

Note that this will miss classes which do not follow conventions, for example which are defined in the default package or whose name do not start by a capitalized letter.

You will also retrieve classes which qualified name starts with an L : this represents arrays, and you might want to strip that L if you only care about the classname. There are other similar single-letters modifiers I can't remember.

Aaron
  • 24,009
  • 2
  • 33
  • 57
  • @JFMeier be careful though, I haven't tested it extensively nor followed the java files specification, I'm pretty sure it must be missing at least some corner cases – Aaron Feb 10 '17 at 18:45
1

Use the JD Java Decompiler (http://jd.benow.ca/).

Jool
  • 1,706
  • 16
  • 14
  • I would have definitely looked into that if it were not blocked by our company network as "Streaming Media/MP3" ;-) – J Fabian Meier Feb 10 '17 at 12:29
  • I don't know why that would be the case. There is a reference to the site from within Wikepedia too. https://en.wikipedia.org/wiki/Java_Decompiler . Perhaps you could ask your network guys to look into it. – Jool Feb 10 '17 at 12:31
  • Maybe they'll let you access the github repo: https://github.com/java-decompiler – Jool Feb 10 '17 at 12:36
  • Link to the downloadable .jar file: https://github.com/java-decompiler/jd-gui/releases/download/v1.4.0/jd-gui-1.4.0.jar – Jool Feb 10 '17 at 12:50
  • I feel like this won't provide more insight than `javap`, maybe I missed a feature? I mean, its output is obviously more human readable, but that doesn't matter if the goal is to programmatically provide a list of referenced classes : you don't want to have to manually parse neither the bytecode nor the source to search for them. – Aaron Feb 10 '17 at 13:27
  • You can also use the jar as a library for its API (JD-Core) (I haven't tried that). javap is certainly an option if you want to do more than browse the class names. – Jool Feb 10 '17 at 13:46
1

An alternative solution is put a JDK1.8 on an accessible network drive and call jdeps there. This works even when the local JDK is 1.7.

J Fabian Meier
  • 33,516
  • 10
  • 64
  • 142