jdeps
JDeps是Java依賴關系分析工具 ,這是一個指令行工具,它處理Java位元組碼(意味着.class檔案或包含它們的JAR),并分析類之間靜态聲明的依賴關系。 可以用各種方式過濾結果,并可以将其彙總到包或JAR級别。 JDeps還可以告訴您您的項目正在使用哪些JDK内部API,并且完全了解子產品系統 。 總而言之,它是檢查各種形式的依賴圖的非常有用的工具。
在這篇文章中,我将向您介紹JDeps的工作方式-後續文章将向您展示一些很好的用例。 對于此探索,我鼓勵您繼續進行,最好是執行您的一個項目。 如果您有一個項目的JAR,并且在它旁邊是一個包含所有傳遞依賴項的檔案夾,這将是最容易的。 如果您使用的是Maven,則可以通過maven-dependency-plugin的copy-dependencies目标實作後者。 使用Gradle,您可以使用複制任務,從設定為configuration.compile或configuration.runtime 。
作為示例項目,我選擇了Scaffold Hunter :
Scaffold Hunter是基于Java的開源工具,用于對資料集進行可視化分析,重點是生命科學中的資料,旨在直覺地通路大型和複雜的資料集。 該工具提供多種視圖,例如圖形,樹狀圖和圖解視圖,以及分析方法,例如用于聚類和分類
我下載下傳了2.6.3版本的ZIP,并将所有依賴項都複制到了libs中。
當顯示輸出時,我将scaffoldhunter(在軟體包名稱中)和scaffold-hunter(在檔案名稱中)縮寫為sh以使其更短。
認識JDeps
從Java 8開始,您就可以在JDK的bin檔案夾中找到JDeps可執行檔案jdeps。如果在指令行上可以找到JDeps可執行檔案jdeps,則最容易使用它,對此您可能必須執行一些特定于作業系統的設定步驟。 確定jdeps –version可以正常工作并顯示Java 9版本正在運作。
下一步是擷取JAR并将JDeps設定為寬松。 在不使用其他指令行選項的情況下使用,它将首先列出代碼所依賴的JDK子產品。 緊随其後的是軟體包級别的依賴關系清單,其組織為<package>-> <package> <module / JAR>。
調用jdeps sh-2.6.3.jar會得到以下輸出:
$ jdeps sh-2.6.3.jar
sh-2.6.3.jar -> java.base
sh-2.6.3.jar -> java.datatransfer
sh-2.6.3.jar -> java.desktop
sh-2.6.3.jar -> java.logging
sh-2.6.3.jar -> java.prefs
sh-2.6.3.jar -> java.sql
sh-2.6.3.jar -> java.xml
sh-2.6.3.jar -> not found
edu.udo.sh -> com.beust.jcommander not found
edu.udo.sh -> edu.udo.sh.data sh-2.6.3.jar
edu.udo.sh -> edu.udo.sh.gui sh-2.6.3.jar
edu.udo.sh -> edu.udo.sh.gui.util sh-2.6.3.jar
edu.udo.sh -> edu.udo.sh.util sh-2.6.3.jar
edu.udo.sh -> java.io java.base
edu.udo.sh -> java.lang java.base
edu.udo.sh -> javax.swing java.desktop
edu.udo.sh -> org.slf4j not found
[... truncated many more package dependencies ...]
您可以看到Scaffold Hunter依賴于子產品java.base (當然), java.desktop (這是一個Swing應用程式), java.sql (資料集存儲在SQL資料庫中)以及其他一些子產品。 這之後是一長串的軟體包依賴項,這有點麻煩。請注意,有些依賴項被标記為未找到,這很有意義,因為我沒有告訴JDeps在哪裡尋找它們。
現在是時候使用各種選項來配置JDeps了。 您可以使用jdeps -h列出它們。
包括依賴項
JDeps的一個重要方面是,它使您可以像分析代碼一樣将其依賴性進行分析。 達到該目标的第一步是使用–class-path将它們放到類路徑中。
這使JDeps可以遵循進入依賴項JAR的路徑,并使您擺脫未找到的名額。 要實際分析依賴關系,還需要使用-recursive或-R将JDeps遞歸到它們。
為了包括Scaffold Hunter的依賴關系,我使用–class-path'libs / *'和-recursive執行JDeps:
$ jdeps --class-path 'libs/*' -recursive sh-2.6.3.jar
[... truncated split package warnings ...]
[... truncated some module/JAR dependencies...]
sh-2.6.3.jar -> libs/commons-codec-1.6.jar
sh-2.6.3.jar -> libs/commons-io-2.4.jar
sh-2.6.3.jar -> libs/dom4j-1.6.1.jar
sh-2.6.3.jar -> libs/exp4j-0.1.38.jar
sh-2.6.3.jar -> libs/guava-18.0.jar
sh-2.6.3.jar -> libs/heaps-2.0.jar
sh-2.6.3.jar -> libs/hibernate-core-4.3.6.Final.jar
sh-2.6.3.jar -> java.base
sh-2.6.3.jar -> java.datatransfer
sh-2.6.3.jar -> java.desktop
sh-2.6.3.jar -> java.logging
sh-2.6.3.jar -> java.prefs
sh-2.6.3.jar -> java.sql
sh-2.6.3.jar -> java.xml
sh-2.6.3.jar -> libs/javassist-3.18.1-GA.jar
sh-2.6.3.jar -> libs/jcommander-1.35.jar
[... truncated more module/JAR dependencies...]
edu.udo.sh -> com.beust.jcommander jcommander-1.35.jar
edu.udo.sh -> edu.udo.sh.data sh-2.6.3.jar
edu.udo.sh -> edu.udo.sh.gui sh-2.6.3.jar
edu.udo.sh -> edu.udo.sh.gui.util sh-2.6.3.jar
edu.udo.sh -> edu.udo.sh.util sh-2.6.3.jar
edu.udo.sh -> java.io java.base
edu.udo.sh -> java.lang java.base
edu.udo.sh -> javax.swing java.desktop
edu.udo.sh -> org.slf4j slf4j-api-1.7.5.jar
[... truncated many, many more package dependencies ...]
在這種特定情況下,輸出以一些拆分程式包警告開頭,我現在将忽略它們。 以下子產品/ JAR和程式包的依賴關系與以前類似,但現在都可以找到,是以它們的數量更多。 但是,這會使輸出變得更加壓倒一切,是以現在該是時候探讨如何從如此大量的資料中弄清楚了。
配置JDeps的輸出
有多種方法可以配置JDeps的輸出。 也許在任何項目的第一次分析中使用的最佳選擇是-summary或-s,它們僅顯示JAR之間的依賴關系,而忽略包的依賴關系。 下表列出了各種其他方式來擷取有關依賴關系的不同觀點:
選項 | 描述 |
---|---|
–package或-p | 其次是隻考慮在該包,這是看哪裡使用這些utils的所有地方一個偉大的方式依賴包名。 |
–regex或-e | 後跟一個正規表達式,它僅考慮對與正規表達式比對的類的依賴。 (請注意,除非使用-verbose:class,否則輸出仍會顯示包。) |
-filter或-f | 後跟一個正規表達式,它排除對與正規表達式比對的類的依賴。 (請注意,除非使用-verbose:class,否則輸出仍會顯示包。) |
-filter:存檔 | 在許多情況下,工件内的依賴性不是那麼有趣。 該選項将忽略它們,僅顯示跨工件的依賴性。 |
–僅API | 有時,尤其是在分析庫時,您隻關心JAR API。 使用此選項,僅檢查公共簽名和公共類的受保護成員的簽名中提到的類型。 |
指令行上的輸出是檢查細節并深入研究有趣的位的好方法。 但是,它并不能提供最直覺的概述-圖表要好得多。 幸運的是,JDeps具有–dot-output選項,該選項可為每個單獨的分析建立.dot檔案 。 這些檔案是純文字,但是可以使用其他工具(例如Graphviz)從它們建立圖像。
這兩個指令産生下圖:
$ jdeps --class-path 'libs/*' -recursive --dot-output dots sh-2.6.3.jar
$ dot -Tpng -O dots/summary.dot
深鑽
如果您想了解更多細節,-verbose:class将列出類之間的依賴關系,而不是将它們聚合到包級别。
有時,僅列出對程式包或類的直接依賴關系是不夠的,因為它們可能實際上不在您的代碼中,而是在您的依賴關系中。 在這種情況下,-inverse或-I可能會有所幫助。 給定要查找的特定程式包或正規表達式,它會一直跟蹤依賴關系,并在此過程中列出工件。 不幸的是,似乎沒有直接方法可以在類級别而不是工件上檢視結果。
在您的特定情況下,還有其他一些選項可能會對您有所幫助–如前所述,您可以使用jdeps -h列出它們。
JDeps和子產品
就像借助子產品系統一樣,編譯器和JVM可以在更高的抽象級别上運作 ,JDeps也可以。 可以使用–module-path指定子產品路徑(請注意-p已經保留,是以它不是此選項的簡寫形式),而初始子產品可以使用–module或-m指定。 從那裡,我們上面所做的分析可以完全相同。
因為Scaffold Hunter尚未子產品化,是以我将切換到我的書中使用的關于Java 9子產品系統的示例項目Monitor應用程式 。 在這裡,我正在建立子產品關系的摘要分析:
# on `master` branch
$ jdeps --module-path mods:libs -m monitor -summary -recursive
[... truncated some module dependencies...]
monitor -> java.base
monitor -> monitor.observer
monitor -> monitor.observer.alpha
monitor -> monitor.observer.beta
monitor -> monitor.persistence
monitor -> monitor.rest
monitor -> monitor.statistics
monitor.observer -> java.base
monitor.observer.alpha -> java.base
monitor.observer.alpha -> monitor.observer
monitor.observer.beta -> java.base
monitor.observer.beta -> monitor.observer
monitor.persistence -> java.base
monitor.persistence -> monitor.statistics
monitor.rest -> java.base
monitor.rest -> monitor.statistics
monitor.rest -> spark.core
monitor.statistics -> java.base
monitor.statistics -> monitor.observer
slf4j.api -> java.base
slf4j.api -> not found
spark.core -> JDK removed internal API
spark.core -> java.base
spark.core -> javax.servlet.api
spark.core -> jetty.server
spark.core -> jetty.servlet
spark.core -> jetty.util
spark.core -> slf4j.api
spark.core -> websocket.api
spark.core -> websocket.server
spark.core -> websocket.servlet
[... truncated more module dependencies...]
除此之外,還有一些Java 9和特定于子產品的選項。 使用–require <modules>,您可以列出所有需要命名子產品的子產品。 您可以使用–jdk-internals分析項目的問題依賴關系,以及–generate-module-info或–generate-open-module建立子產品描述符的初稿。 正如前面提到的,JDeps還将始終報告其找到的所有拆分包。
在以後的文章中,我将向您展示如何使用這些标志來幫助您的項目進行子產品化。
擷取我的書,并了解有關如何在Java 9遷移中使用JDeps的更多資訊!
Java 9子產品系統
- 子產品系統的深入介紹:
- 基本概念和進階主題
- 曼甯(Manning)釋出:
- 自2017年賽事開始提供搶先體驗
-
訂閱我的時事通訊以保持關注。
(甚至可以偷看。)
使用代碼fccparlog可獲得
37%的折扣!
反射
使用JDeps,您可以分析項目的靜态聲明的依賴關系。 它在類級别上運作,但是将結果彙總到包和工件級别。 使用各種過濾器,您可以專注于最重要的方面。 也許最基本的分析是跨代碼和第三方庫的工件依賴關系圖:
$ jdeps --class-path 'libs/*' -summary -recursive sh-2.6.3.jar
它可用于執行一些非常有趣的分析,尤其是在較大的代碼庫上。 我将很快為您展示一些示例。
翻譯自: https://www.javacodegeeks.com/2017/07/jdeps-primer-analyzing-projects-dependencies.html
jdeps