80

is there a tool that can list third party "packages" that contain (third party) classes referenced in the JAR ? Let say that it would recognize what is "home" package from JAR file definition and it would print out a list of fully qualified names of third party classes up to 3rd level that were referenced within the JAR.

org.apache.commons  
org.apache.maven
javax.servlet.jsp
org.eclipse.persistence
org.apache.jackrabbit

the purpose is that I need to find maven dependencies for that JAR file and deploy it as a maven artifact.

lisak
  • 21,611
  • 40
  • 152
  • 243
  • 2
    Isn't Maven supposed for exactly this purpose? – BalusC Dec 11 '10 at 17:09
  • 1
    Imagine that you have an Ant based project and you want to deploy it to maven repository for someone else to use it as a dependency. You must specify its transitive dependencies in pom definition. I need a way that would ease finding them – lisak Dec 11 '10 at 17:14
  • Edit: I know how to do it manually, spending much effort. Automated dependecy resolution should be theoretically possible, all information is in the .jar and in the Maven repository already. – Roman Zenka Dec 11 '10 at 17:16
  • There must be something for that, it is really weird that somebody from sonatype or community hasn't done anything for such an essential thing – lisak Dec 11 '10 at 17:33
  • But how do you manage versions in your case ? This is what maven is for , Isn't ! – srinannapa Dec 11 '10 at 18:49
  • 1
    Check out the copy-dependencies goal in the maven-dependency-plugin. – Thorbjørn Ravn Andersen Jun 28 '12 at 10:44

8 Answers8

57

There is a new tool since JDK 8: jdeps

https://wiki.openjdk.java.net/display/JDK8/Java+Dependency+Analysis+Tool

jdeps is a new command-line tool added since JDK 8 for developers to use to understand the static dependencies of their applications and libraries. jdeps is a static analysis tool on the given class files

Barry Kelly
  • 41,404
  • 5
  • 117
  • 189
  • 2
    A little hint: the generated graph can contain a lot of packages, and can get very wide. To organize it in vertical add in the grap definition (inside digraph): graph [ rankdir = "LR" ]; – user1708042 Mar 31 '20 at 13:35
  • 1
    jdeps doesn't work for me. I just get the error 'Exception in thread "main" java.lang.InternalError: Missing message: warn.skipped.entry' – devinbost Oct 21 '21 at 16:57
26

JarAnalyzer:

a dependency management utility for jar files. It's primary purpose is to traverse through a directory, parse each of the jar files in that directory, and identify the dependencies between the jar files. The output is an xml file representing the PhysicalDependencies between the jar files.

For more information on PhysicalDependencies, including a variety of design patterns, check out Extensible Java...

gnat
  • 6,213
  • 108
  • 53
  • 73
MJB
  • 9,352
  • 6
  • 34
  • 49
23

You can do the following (if its a maven project):

mvn dependency:tree

It shows transitive dependencies as well, making it very useful to debug dependency conflicts.

karthik manchala
  • 13,492
  • 1
  • 31
  • 55
4

If you use maven (as I understood), you can simply use Maven Dependency plugin.

First you need to write a basic pom.xml with all your jars, you can copy this example (i use hibernate as example), and substitute your jars :

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
       <modelVersion>4.0.0</modelVersion>
       <groupId>com.mycompany.app</groupId>
       <artifactId>my-app</artifactId>
       <version>1.0-SNAPSHOT</version>
       <packaging>jar</packaging>
       <name>Maven Quick Start Archetype</name>
       <url>http://maven.apache.org</url>
       <dependencies>
          <dependency>
             <groupId>org.hibernate</groupId>
             <artifactId>hibernate-core</artifactId>
             <version>3.5.0-Final</version>
          </dependency>
<!-- add here other dependencies -->
       </dependencies>
    </project>

then open terminal, go into the containing folder of the pom.xml above and run this command :

mvn dependency:tree

this will print a list of dependencies...

or if you want download and copy in a folder all dependencies run the following command :

mvn dependency:copy-dependencies

you'll find all your dependencies in folder ./target/dependencies

obe6
  • 1,743
  • 15
  • 23
3

Tattleltale is a tool from JBoss which does this

tattletale.jboss.org/

  • I can't get this to work for my jar. I just get a flood of messages like 'java.io.IOException: invalid constant type: 15' – devinbost Oct 21 '21 at 17:04
2

My first thought was that you could do this by using a class loader to iterate over all the class files in the jar and use reflection to analyse each one for their dependences. However the Class class does not have a method which tells you this information. So the next thought would be to use some sort of bytecode analyser (asm for example) to pull out all the referenced classes from a compile class.

Presuming that you could get this information the next issue would be to back trace the classes to jars. In a sense this would be the easy part because all you would need to do is create a classloader for each jar in your maven repo, or directory or wherever the jars are, and then ask each one in turn if it contained the specific class.

The flaw in that thinking is that a java class (raw source or compiled) does not detail where to get the imported class from. So if you have two classes with the same package and name (happens more often than you might think), then you would be unable to tell which to use.

Even java just assumes that the first one it finds in the class path is the correct one and throws an exception if it turns out to be incorrect (MethodNotFoundException). So unless you are going to further analyse the bytecode to figure out what methods on each class are called and then compare those with the classes in your class path, you still won't be able to be correct.

IN short, it's probably possible to do what you want, but likely to be very difficult and time consuming.

The way I normally deal with this is to simply fire up the class in test code and keep adding dependencies until I can get it to execute every method I'm interested in.

drekka
  • 20,957
  • 14
  • 79
  • 135
  • Hi Derek, thank you for your thoughts. It would be quite time demanding. I'm gonna accept MJB's answer because JarAnalyzer is exactly what I was searching for. If it supported recursive directory search, it would practically list maven dependencies you need. No version numbers and usable output of course, but you could set up the pom definition quite easy with it. – lisak Dec 16 '10 at 21:29
1

This might be an alternative for this tool. But it doesn't list referenced classes. The last number determines "package level".

jar tvf yourjar.jar | perl -nle'BEGIN{$depth=(shift)-1}print join(".", (split(/\//, (split)[-1]))[0..$depth])' 3

Problem is, that this way it is impossible to get referenced classes out of class definitions. So the only way possible seems to be do it in JAVA.

So the question is: Is there any Java tool that can do it ?

EDIT:

I found what I needed : M2eclipse has a feature called Class search

In the maven repositories view, right click a repository and enable full index

Then Navigate > Open type from maven - there you can look through all artifacts available based on java package convention

lisak
  • 21,611
  • 40
  • 152
  • 243
  • Getting there. Now you need to turn the list of packages into a list of jars that contain them. The list would be large (multiple versions of libraries), so you would like to check for interface compatibility and find the best matching one - it would be a lot of work to write, but it sounds doable. I would call it `autolinker` – Roman Zenka Dec 11 '10 at 17:32
  • And what would I search through to find the JARs ? local maven repository ? It would be impossible to search through remote maven repo in this situation – lisak Dec 11 '10 at 17:35
  • This doesn't give dependency versions. – devinbost Oct 21 '21 at 17:06
1

If yours is a maven based project

mvn dependency:build-classpath -Dmdep.pathSeparator=":" -Dmdep.prefix='' -Dmdep.fileSeparator=":" -Dmdep.outputFile=classpath

Look at the below link http://maven.apache.org/plugins/maven-dependency-plugin/build-classpath-mojo.html

May be in your case

mvn dependency:build-classpath -Dmdep.pathSeparator=":" -Dmdep.prefix='' -Dmdep.fileSeparator=":" -Dmdep.outputFile=classpath -f pathtopom.xml of third party 
srinannapa
  • 3,085
  • 8
  • 49
  • 66
  • The point of this question is listing all classes referenced in a JAR in a human readable form : up to 3rd - 5th level : "org.apache.commons.blabla" ....to set up a dependency list for the JAR to deploy it as a maven artifact – lisak Dec 11 '10 at 18:37
  • You can read the output produced by above command and use it for deployment ! – srinannapa Dec 11 '10 at 19:07
  • look, all you have is some JAR and you want to create a pom definition for it and deploy it as an artifact... I do not have any maven project... I just want to define its transitive dependencies...I'm not sure you understand what is the point of this question – lisak Dec 11 '10 at 19:19
  • ok. so you don't have maven enabled pom for the jar you are inputti ng . Infact most of the projects(open source projects) are now enabled to maven , anyways that is different story again. Even if you acheive , You must have to take care about versions of the jar's even if you get artifact id using the fully qualified name , one can't predict the version , the only version downloaded would be latest one from maven repo. – srinannapa Dec 11 '10 at 20:03