How to analyze transitive Java dependencies
We stand on the shoulders of giants. Most of our code relies on code from others that we use as libraries. In gradle we can include such libraries as simple as adding implementation "another.library:that-i-can-use:1.0.0"
to the build.gradle
. Most of those libraries, again, build on top of yet other libraries. In the end, our code indirectly depends on way more libraries than we might think. Those indirect dependencies are also called transitive dependencies.
We have some tools to investigate those dependencies. For example in Android Studio (and other IDEA based IDEs) we can analyze dependencies (including transitive dependencies) in the Project Structure window:
Open the Project Structure window via Find Action:
In the Project Structure window select the Dependencies-tab on the left and chose a module (the modules may take a few seconds to load). Under Resolved Dependencies on the right, you can now browse the dependency tree:
If you prefer the command-line, you can use gradle to print a dependency tree:
./gradlew :module-name:dependencies
The output looks something like this:
debugRuntimeClasspath - Runtime classpath of compilation 'debug' (target (androidJvm)).
+--- com.android.support:multidex:1.0.1 -> androidx.multidex:multidex:2.0.0
+--- org.jetbrains.kotlin:kotlin-android-extensions-runtime:1.3.61
| \--- org.jetbrains.kotlin:kotlin-stdlib:1.3.61 -> 1.3.70
| +--- org.jetbrains.kotlin:kotlin-stdlib-common:1.3.70
| \--- org.jetbrains:annotations:13.0
+--- org.jetbrains.kotlin:kotlin-stdlib:1.3.61 -> 1.3.70 (*)
+--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.5
| +--- org.jetbrains.kotlin:kotlin-stdlib:1.3.70 (*)
| \--- org.jetbrains.kotlin:kotlin-stdlib-common:1.3.70
\--- androidx.constraintlayout:constraintlayout:1.1.3
\--- androidx.constraintlayout:constraintlayout-solver:1.1.3
I also like to browse mvnrepository.com. It makes it very easy to see transitive dependencies and follow them with a single click:
As we saw, we do not only depend on a few libraries but on fully-fledged library trees. I hope this post introduced you to your new favorite way of analyzing dependencies. Have fun!