簡體   English   中英

Maven 如何使用 ClassLoader 加載類

[英]How Maven loads classes using ClassLoader

我目前對 Java 中的 ClassLoader 的了解有點晦澀。 那是因為到目前為止,我還沒有找到任何適合 CLassLoader 初學者的好的文檔。 我正在尋找的正是與 Maven 相關的內容。 聲明免責聲明,讓我進入我的問題。

我正在編寫一個 Spring MVC 應用程序,我決定研究如何使用 ClassLoader 加載依賴項 - Jars 和類。 我發現是根據ClassLoader的文檔,Jar中的類是從CLASSPATH加載的,我可以在.m2/repository目錄下看到它們,但是CLASSPATH沒有產生任何東西,它實際上是空的。

Can somebody please explain to me, how the classes from JAR are loaded into JVM Memory using ClassLoader using Maven, if the CLASSPATH is empty.

謝謝

你混淆了一些事情。

類加載器

ClassLoader 是一個運行時概念。 Maven 是一個編譯時概念。 因此,一個與另一個沒有任何關系。 Maven 和 ClassLoader 不交互。 完全沒有。

When you start a basic java app ( java -jar foo.jar or java com.foo.MainClass ), you get 2 classloaders. 一個加載程序將加載系統內容:例如java.lang.String 可執行文件本身“只知道”如何執行此操作(您不需要配置PATHCLASSPATHJAVA_HOME - 它可以正常工作); 到java 8,自動找到rt.jar ,其中包含String.class等核心類。 從 java 11 開始,它會在您的 java 發行版中找到 jmod 文件。

然后,一旦虛擬機“啟動”,虛擬機就會創建另一個類加載器,同樣基於其內置的東西:應用類加載器。

這個使用“類路徑”。 其來源取決於您如何運行 java 應用程序:

  • java -jar somejar.jar

在這種情況下,類路徑的來源是 jar 清單中的Class-Path:行(位於META-INF/MANIFEST.MF的文件)。 僅此而已- CLASSPATH 環境變量以及任何-cp-classpath選項都將被完全忽略。

  • java -cp a.jar:b.jar:. com.foo.ClassName

請注意, -cp-classpath的縮寫(它們的意思相同):在這里,類路徑被視為列出的所有文件和目錄(在 windows 上,使用;作為分隔符),然后從那里加載類。 包括com.foo.ClassName本身。

  • java com.foo.ClassName

如果您沒有明確指定 -cp 參數,則使用環境變量 CLASSPATH。 你不想要這個。 始終指定類路徑。

那是運行時 - maven 與此無關。

做你自己的

您可以制作自己的 ClassLoader; 抽象是這樣的,它所要做的就是將資源名稱轉換為字節。 而已。 您可以制作一個 ClassLoader(字面意思是! public class MyLoader extends java.lang.ClassLoader {... } ),它可以從網絡加載數據,或者即時生成數據,或者從加密的數據存儲中獲取數據。 隨你喜歡。

使用像這樣的自定義類加載器是在“奇怪”位置(不是 jar 文件或目錄)查找類的解決方案,以及允許 java 動態“重新加載類”的機制 - 在開發時非常有用,例如 java ,而不使用像 eclipse 這樣的熱代碼替換調試器。 ClassLoaders 是一種機制,通過該機制,web 服務器可以具有以下功能:“我從某個預配置目錄加載 jars 或戰爭……如果您替換 Z68995FCBF432492D15484D04A9D2AC40,則將看到它。”

編寫自己的 ClassLoader 接近於火箭科學,通常不需要,除非你正在編寫應用程序服務器。 不是普通的工作。

Maven

要編譯源代碼,編譯器必須知道你引用的所有類型的方法和字段等。 你不能編譯"Hello".toLowerCase(); 如果編譯器不知道String包含什么。

因此,編譯器有“我需要查找類”的概念。 但這不稱為class loading ,值得注意的是, maven從不加載任何類 如果是這樣,任何 class 中的任何 static 初始化程序都會運行,並且會弄亂你的編譯。 Maven 只是檢查 class 文件,從不讓 VM 實際加載它,以了解提供了哪些方法和字段等。

java.lang.ClassLoader 不參與其中

javac本身也有一個-classpath選項。 maven 也是如此,真的。

Maven 通過放置已經為您編譯的內容(例如,在編譯src/test/java中的內容時,來自src/main/java的編譯內容位於類路徑中)以及所有依賴項,自動構建類路徑。 如何? 嗯,有關系嗎? Maven 可以。 它構造了一個大的目錄列表和 jars 並通過-classpath參數將其傳遞給javac

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM