2010-03-10 62 views
11

在Tomcat 5.5服務器上,我在系統類路徑中放置了一個類(並修改了catalina.bat來選擇它),或者將類放在共享lib目錄中。現在如果我有兩個不同的應用程序使用相同的類,它們的WEB-INF lib/classes目錄中沒有該類,它們將使用該類的同一個實例。我理解一個類加載器將委託給它的父類加載器以查找類的概念,因爲在這種情況下,因爲該類不存在於WEB-INF/classes或WEB-INF/lib中, WebAppX類加載器將分別嘗試共享,通用和系統類加載器。Tomcat上有多個應用程序的類加載器行爲

但是,這對我來說似乎很奇怪,即兩個不同的應用程序可以使用此方法共享上下文。有人能幫我理解爲什麼這樣。例如在下面的代碼中,兩個servlet每個都在單獨的戰爭中部署,而CommonCounter是共享的,並且他們可以讀取由另一個增加的計數器值。

編輯 這似乎直覺,我認爲兩個獨立的應用程序可以共享以這種方式的上下文。事實上,如果他們有相同的類實例,他們甚至可以在兩個不同的應用程序中實現多線程/同步,這看起來非常不直觀。

package com.test; 
public class CommonCounter { 

    public static int servlet1; 
    public static int servlet2; 
} 




public class Servlet1 extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet { 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
     CommonCounter.servlet1++; 
     System.out.println("Other one had "+CommonCounter.servlet2+" hits"); 
    } 
} 



public class Servlet2 extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet { 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
     CommonCounter.servlet2++; 
     System.out.println("Other one had "+CommonCounter.servlet1+" hits"); 
    } 
} 
+1

我不明白這個問題:你自己解釋一下,Tomcat的系統類加載器中的類是在所有應用程序之間共享的。因此,這兩個應用程序訪問相同的類,從而讀取相同的靜態字段,並可以看到彼此的效果。 – 2010-03-10 12:04:22

+0

是的,但我覺得兩個獨立的應用程序可以以這種方式共享上下文。事實上,如果他們有相同的類實例,他們甚至可以在兩個不同的應用程序中實現多線程/同步,這看起來非常不直觀。 – saugata 2010-03-10 12:12:44

回答

10

正如評論說,你已經正確地解釋了爲什麼你觀察你觀察到的行爲。

關鍵是如何構造ClassLoaders。一個JVM中的兩個ClassLoader完全可以加載一個類,因此包含靜態字段的單獨獨立副本。 「靜態」使一個ClassLoader,而不是一個JVM'全球'。我想,Tomcat不能擁有帶共享庫的容器級ClassLoader,並且強迫每個應用程序ClassLoader單獨加載共享庫。

但是,對於其他常見的類,比如J2EE API和實現,這會有點浪費。原則上,類不應該依賴於這個ClassLoader結構。

這就是爲什麼你不應該把應用程序依賴關係放在Tomcat的共享庫文件夾中。這是'解決方案'。它將應用程序綁定到容器的特定設置和部署,這違背了J2EE Web應用程序的原則。只需爲每個應用程序在WEB-INF/lib中放置依賴關係的副本。

您觀察到的行爲是另一個不這樣做的原因:應用程序變得彼此間隔較小。它不會讓我成爲違反直覺的行爲,但是這只是因爲我習慣了Tomcat的工作方式並思考這些事情。

+0

我遇到了類似的問題,我需要在兩個webapps之間共享對象。在我看來,將對象放入系統類加載器可能是唯一的解決方案。看到http://stackoverflow.com/questions/9453109/using-jndi-to-share-servlet-session-objects-and-data-in-tomcat – ziggy 2012-02-27 14:07:25

+1

也許......但跨webapps共享絕對不是你的東西打算這樣做。 (儘管查看.ear文件)出於上述原因,它可能正常工作,但無法保證正常工作。 – 2012-02-28 15:37:19

相關問題