2018-10-21

Java 9 : jdeps

This tool analyses your code base specified by the path to the .class file, directory, or  JAR, lists the package-wise dependency of your application, and also lists the JDK module in which the package exists. This helps in identifying the JDK modules that the application depends on and is the first step in migrating to modular applications.

We can run the tool on our HelloWorldXml example written earlier and see what jdeps provides:

$> jdeps mods/com.packt/
com.packt -> java.base
com.packt -> java.xml.bind
com.packt -> java.io                                  java.base
com.packt -> java.lang                              java.base
com.packt -> javax.xml.bind                     java.xml.bind
com.packt -> javax.xml.bind.annotation   java.xml.bind



Using jdeps to find dependencies in a Java application

The first step in modularizing your application is to identify its dependencies. A
static analysis tool called jdeps was introduced in JDK 8 to enable developers to find
the dependencies of their applications. There are multiple options supported in the
command, which enables developers to check for dependencies to the JDK internal
APIs, show the dependencies at the package level, show the dependencies at the
class level, and filter the dependencies, among other options.

In the sample code, we also added a call to the deprecated JDK internal API, called
sun.reflect.Reflection.getCallerClass(). This way, we can see how jdeps helps in
finding dependencies to the JDK internal APIs.

The following steps will help you to set up the prerequisites for this recipe:

1. You can get the complete code for the sample from the location, chp3/1_jsonjackson-sample. 
We have built this code against Java 9 and it compiles well. So,
you need not install something other than Java 9 to compile it.

2. Once you have the code, compile it by using the following:
#On Linux
javac -cp 'lib/*' -d classes -sourcepath src $(find src -name *.java)
#On Windows
javac -cp lib\*;classes -d classes src\com\packt\model\*.java
src\com\packt\*.java

You will see a warning for the use of an internal API, which you can safely
ignore. We added this with a purpose to demonstrate the capability of jdeps.
Now, you should have your compiled class files in the classes directory.

3. You can run the sample program by using the following:
#On Linux:
java -cp lib/*:classes/ com.packt.Sample
#On Windows:
java -cp lib\*;classes com.packt.Sample

4. We have provided the run.bat and run.sh scripts at chp3/1_json-jackson-sample.
You can compile and run using these scripts as well.

5. Let's also create a JAR file for this sample so that we can run jdeps on the JAR
file as well:
jar cvfm sample.jar manifest.mf -C classes .


1. The simplest way to use jdeps is as follows:
jdeps -cp classes/:lib/* classes/com/packt/Sample.class

The preceding command is equivalent to the following:
jdeps -verbose:package -cp classes/:lib/*
classes/com/packt/Sample.class


2. Let's list the dependencies at the class level:
jdeps -verbose:class -cp classes/:lib/*
classes/com/packt/Sample.class


3. Let's get the summary of the dependencies:
jdeps -summary -cp classes/:lib/* classes/com/packt/Sample.class


4. Let's check for the dependency on the JDK internal API:
jdeps -jdkinternals -cp classes/:lib/*
classes/com/packt/Sample.class

5. Let's run the jdeps on the JAR file, sample.jar:
jdeps -s -cp lib/* sample.jar

6. Let's find if there are any dependencies to a given package name:
jdeps -p java.util sample.jar

The -p option is used to find dependencies on the given package name. So,

we get to know that our code depends on the java.util package. Let's try with
some other package name:

jdeps -p java.util.concurrent sample.jar

There is no output, which means that our code doesn't depend on the
java.util.concurrent package.

7. We would want to run the dependency check only for our code. Yes, this is
possible. Suppose we run jdeps -cp lib/* sample.jar, you will see even the
library JARs being analyzed. We wouldn't want that, right? Let's just include
the classes of the com.packt package:
jdeps -include 'com.packt.*' -cp lib/* sample.jar


8. Let's check whether our code is dependent on a specific package:
jdeps -p 'com.packt.model' sample.jar


9. We can use jdeps on analyzing the JDK modules. Let's pick the java.httpclient
module for analysis:
jdeps -m java.httpclient

We can also find whether a given module is dependent on another module by
using the --require option, as follows:
jdeps --require java.logging -m java.sql

jdeps command 

There are a few more related to filtering the dependencies and filtering the classes to be analyzed. Apart from that, there are a few options that deal with module paths.
The following are the options that can be tried out:
-e, -regex, --regex:

These find dependencies matching the given pattern.
  • -f, -filter: These exclude dependencies matching the given pattern.
  • -filter:none: This allows no filtering applied via filter:package or filter:archive.
  • -filter:package: This excludes dependencies within the same package. This is
  • the default option. For example, if we added -filter:none to jdeps sample.jar, it
  • would print the dependency of the package to itself.
  • -filter:archive: This excludes dependencies within the same archive.
  • -filter:module: This excludes dependencies in the same module.
  • -P, -profile: This is used to show the profile of the package, whether it is in
  • compact1, compact2, compact3, or Full JRE.
  • -R, -recursive: These recursively traverse all the runtime dependencies; they are
  • equivalent to the -filter:none option.

No comments:

Post a Comment