簡體   English   中英

Tomcat類加載器如何在同一個JVM中分離不同的Webapps對象作用域?

[英]How Tomcat Classloader separates different Webapps object scope in same JVM?

由於Tomcat可以同時加載多個webapp,並且這些webapp可以單獨工作,並且不會互相干擾,並且它們可以在同一個JVM中工作。 所以我對tomcat如何在同一個JVM中處理Object作用域感到困惑。

例如,我在兩個不同的Webapps中都有一個單例對象,而tomcat將為每個Web應用程序生成兩個不同的單例對象。 我一直認為單例對象在同一個JVM中只有一個對象,但在tomcat JVM中可能有兩個或更多。


我已經閱讀了有關ClassLoader的一些信息,Tomcat有自己的WebAppClassLoader來加載webapps。 那么這意味着這里的對象范圍是ClassLoader還是我錯了。 有誰知道這個或者可以給我一些關於tomcat工作內存布局的信息?

所有秘密都在那些ClassLoader實例之后。

類的狀態(像所有靜態變量,字節代碼等)由加載該類的類加載器確定范圍(類由其名稱和加載類的類加載器標識。這不是范圍,但是考慮范圍通常有助於更好地理解這一點)。

因此,如果一個類由兩個不同的類加載器加載,則該類在VM中存在兩次,它具有兩組靜態字段,可以具有不同的字節代碼(如不同的方法實現)以及所有這些。 “普通”Java應用程序具有由類加載器層次結構加載的所有類,並且每個類僅加載一次。

對於更復雜的場景,您將需要不同的行為。 有時你想要隔離一個庫而不是弄亂你的代碼(比如eclipse中的插件或應用程序服務器中的web應用程序)。

將程序與其他類隔離的基本思想是使用額外的類加載器加載它們並使用大量的反射。 如果您想閱讀本文,請查看Oracle關於ClassLoadersOSGI的文檔。

Tomcat(以及許多其他Web容器/應用程序服務器)使用單獨的ClassLoader層次結構加載應用程序。 這將所有類與其他(Web)應用程序隔離開來,因此也確保單例,不同類版本和所有這些內容不會發生沖突。

請記住,Java中的類由其完全限定名稱 加載它的類加載器標識。 Tomcat為您部署的每個上下文(Web應用程序)使用單獨的類加載器,從而將它們分開。 此外,系統類加載器加載tomcat特定庫,JVM引導加載程序加載Java核心庫。

在談論單身人士時,總會被遺漏的一件事是,單身人士每個類加載器只能有一個實例。 ClassLoader限制了類可見性,因此同一個VM中的幾個不同的類加載器下可以存在相同的類。 除此之外,這允許您同時加載不同版本的jar。

這個問題: Java類加載器似乎有一些很好的鏈接和資源可供進一步研究。

在普通的Java應用程序中,當要求類加載器加載一個類時,它會將請求委托給它的父類加載器,然后在父類加載器找不到所請求的類時加載它。

對於Web應用程序服務器,這略有不同 對於像tomcat這樣的Web應用程序服務器中部署的每個Web應用程序,通常都有不同的類加載器。 對於Tomcat,它看起來如下 -

在此輸入圖像描述

因此對於Web應用程序類加載資源按以下順序發生 -

  1. JVM的引導類(核心java類)
  2. / WEB-INF /您的Web應用程序的類
  3. 您的Web應用程序的/WEB-INF/lib/*.jar
  4. 系統類加載器類(Tomcat / Classpath特定類)
  5. 常見的類加載器類(所有Web應用程序通用的類)

但請注意,如果使用delegate="true"配置Web應用程序類加載器,則更改順序 -

  1. JVM的引導類(核心java類)
  2. 系統類加載器類(Tomcat / Classpath特定類)
  3. 常見的類加載器類(所有Web應用程序通用的類)
  4. / WEB-INF /您的Web應用程序的類
  5. 您的Web應用程序的/WEB-INF/lib/*.jar

有關更多詳細信息,您可以查看Apache Tomcat的Class Loader HOW-TO頁面。

JVM中類的“ID”由完全限定的類名和用於加載它的類加載器組成。 這意味着,如果您通過不同的類加載器加載兩個具有相同名稱的類,則它們被視為不同的類。

因此,單例將是類加載器的單例 - 在容器/ JVM中; 作為容器/ JVM可能有多個類加載器。

  1. 在tomcat中使用不同的類加載器來分離不同的應用程序。 例如app1使用ClassLoaderA,app2使用classloaderB。
  2. 每個類都將使用自己的類加載器來加載其他類。 因此,如果ClassA.class引用ClassB.class,則ClassB需要位於ClassA或其父類的類加載器的類路徑中。 例如,在app1中,從ClassLoaderA加載com.exmaple.test1。 com.exmaple.test1想要新的com.exmaple.test2()。 默認情況下,它使用自己的類加載器ClassLoaderA來加載com.exmaple.test2。 所以在com.exmaple.test1的視圖中,它只能看到自己的類路徑類(app1 / webapp / classes或app1 / webapp / lib)。 在app2中,它會看到不同的視圖。
  3. 總而言之,學習類加載器必須了解委托模型。 而能見度是孩子可以看到的父母。 但是父母看不到孩子和兄弟姐妹看不到兄弟姐妹。 所以我們可以隔離不同的app。

暫無
暫無

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

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