The problem is that I do not even know what exactly I should search for on google, so that's why I am asking for a short explanation here on SO.
你想要搜索的是「Classloader」。這種類型的對象負責加載Java類。由JVM加載的每個類都由其完全限定名稱和加載它的類加載器的實例標識。這意味着在一個單獨的JVM中,可以有幾個名稱完全爲「com.example.Test」的類,每個類都由不同的類加載器加載 - 並且每個類都有自己的靜態字段。更重要的是,這些類在運行時會被認爲是不同的:從一個類加載器將「com.example.Test」轉換爲其他類加載器的「com.example.Test」將以ClassCastException結束。
爲了避免在多次加載多個常用類(如java.util.List)的情況下,類加載器通常保持在乾淨的層次結構中。每個類加載器都知道它的「父類」,即負責加載「更一般類」的類加載器。當我們嘗試加載一個類(通常是「按名稱」發生的),比如「com.example.OtherTest」,當前類加載器試圖詢問它的父代是否能夠加載它(並且父代又要求其父代, 等等)。這樣,每個類都可以加載它的最普通的類加載器(java.lang.String將始終由標準引導類加載器加載,即使其他一些類加載器有一些不同的版本可用)。
當你部署一場戰爭時,glassfish會爲它創建一個單獨的類加載器。類加載器知道如何從WEB-INF/lib和WEB-INF/classes中加載類。它的父代是(或至少是祖父)域加載器,對所有應用程序都是通用的。因此,在應用程序類加載器加載任何類之前,它會要求Glassfish來完成它。整個過程是相當可配置的,並且使您可以只將一個通用庫的副本加載到JVM中(例如,如果將庫放入-AFAIR - domain1/lib/ext中,它們將可用於域類加載器,每個應用程序的類加載器的祖先;或者你甚至可以把它放在你的JRE的lib/ext文件夾中,並讓它可用於主類加載器,它將爲你運行的任何應用程序加載類)。在這種情況下,他們將共享靜態字段。或者你可以通過war classloader加載你的庫,並且讓所有的靜態字段對你的應用程序「私有」。
'或者你可以讓你的庫被war classloader加載,並且讓所有的靜態字段對你的應用程序「私有」。這意味着如果我在兩個不同的'WARs'中將依賴關係打包兩次,那麼不同的類加載器將會使用? (對於一個愚蠢的問題抱歉,但我只是想確定,這個問題已經困擾了我很長一段時間,我想完全理解發生了什麼)。 – alegen
是的。每個Web應用程序都有自己的類加載器;否則應用程序可能會相互「攻擊」。 – fdreger
btw:類加載的次數不取決於罐子的數量。你可以想象同一個類從同一個文件中加載了10次,由不同的類加載器加載。 – fdreger