載入類是運行程式的基礎,瞭解Java和Tomcat的類載入機制對更有效地開發、調試Web應用程式有一定的積極作用。本文簡單介紹Java和Tomcat的類載入機制,希望對大家有所協助。
在安裝JDK後,其典型的目錄層次如下所示(JDK 1.6.0):
主要的目錄和JAR簡述如下:
- <JAVA_HOME>/bin: 包含在JDK中的開發工具的可執行檔,一般而言,PATH環境變數應包含該目錄。
- <JAVA_HOME>/lib: 開發工具使用的檔案,其中包括(1)tools.jar:該JAR包包含支援JDK中工具類和實用類的非核心類。同時也包含(2)dt.jar:BeanInfo使用的設計時(DesignTime)歸檔檔案,該JAR包告訴IDE如何顯示Java組件和如何讓開發人員定製它們。其中主要包含Swing的相關類。
- <JAVA_HOME>/jre/lib:包含Java運行時環境使用的核心類、屬性設定和資源檔等。例如:(1)rt.jar:引導類(組成Java平台核心API的運行時類);(2)charsets.jar:字元轉換類。
在一個典型的Web應用環境中,在設定CLASSPATH環境變數是,通常需要包含以下條目:
- <JAVA_HOME>/lib/tools.jar。
註:在使用Tomcat作為Servlet/JSP容器的Web環境中,Tomcat在啟動過程中清除了原有CLASSPATH的內容,並對其進行了重新定義。細節見下文。
Java啟動器(java)初始化Java虛擬機器。虛擬機器按照如下順序搜尋載入類:
- 引導類:組成Java平台的類,包括rt.jar和一些別的重要的jar檔案;
- 擴充類:使用Java擴充機制的類,這些類捆綁成JAR檔案,並被放置在擴充目錄中;每一個在jre/lib/ext擴充目錄下的JAR檔案均被設定為一個擴充並使用Java擴充架構載入;
- 使用者類:由開發人員定義的類和沒有利用擴充機制的第三方類,這些類的位置由使用者指定,一般通過使用-classpath命令列選項或者使用CLASSPATH環境變數來指定其位置。
與之相對應,自從J2SE 1.2規範起,JVM就已經利用了三種不同的類載入器:
- 引導類(Bootstrap)載入器(也稱為初始類載入器);
這些類載入器是有層次的,系統類別載入器位於底層,而引導類載入器位於上層,它們之間的關係為父-子關係。
- 引導類載入器:引導類載入器用於JVM載入那些它運行所需的Java類。實際上,引導類載入器負責載入所有核心的Java類(如java.lang.*和java.io.*)。一般各種JVM廠商(包括Sun)使用本地代碼實現引導類載入器。
- 擴充類載入器:Java 1.2引入了標準擴充機制。可以將JAR檔案放置在標準擴充目錄,JVM將能自動地找到它們。擴充類載入器負責載入一個或者多個擴充目錄中的所有類。一般情況下,只要安裝了Java運行環境(JRE),那麼擴充目錄為<JRE>/lib/ext。擴充類載入器可以不是獨立的類載入器,一些實現也許甚至允許引導類載入器從擴充目錄載入類。
- 系統類別載入器:系統類別載入器在CLASSPATH環境變數指定的JAR檔案中尋找自己的類,或通過-classpath命令列選項傳遞該類,如果沒有指定,則預設使用目前的目錄。系統載入器也用於載入應用程式的entry point類(即含有main()方法的類),對於那些其他任何沒有涵蓋在以上兩類載入器中的類,都預設使用系統類別載入器。
- 委派模型:JVM通過利用委派模型知道將使用哪個類載入器。Java JDK 1.2以後的版本,無論類載入器何時收到載入類的請求。在一個類載入器試圖載入一個請求的類之前,它委派該載入請求到其父類類載入器,直到引導類載入器。如果父類載入器成功載入所請求的類,那麼就返回作為結果的類對象,只有當父類載入器未能載入該類的情況下,原始的類載入器才嘗試裝載該類。
註:類載入器的更多行為:
- 懶散載入:上述類載入器並沒有預先載入在搜尋該路徑中的所有類。相反它按要求載入類。這樣的行為稱為懶散載入。
- 類緩衝:標準的Java SE類載入器可以按要求尋找類,但一旦某個類被載入到類載入器中,它將維持載入(緩衝)一段時間。不過,JVM垃圾收集器可以回收這些Class對象。
- 獨立的命名空間:為每個類載入器分配了唯一的命名空間。
- Apache Tomcat 5.5 Servlet/JSP類載入機制:
同其它伺服器應用程式類似,Tomcat 5安裝了多種類載入器(即,實現了java.lang.ClassLoader介面的類),來允許容器的不同部分和運行在容器中的Web應用程式來訪問不同可用類和資源的庫。
當Tomcat 5啟動時,它建立了一套類載入器,這些載入器組織成如下的父子關係,其中父類載入器位於子類載入器之上(Tomcat 6.0版本的類載入器階層發生了變化):
載入器定義如下:
- Bootstrap:該載入器包含由JVM提供的基本的運行時類,加上放置在系統擴充目錄(<JAVA_HOME/jre/lib/ext>)的JAR檔案中的類。註:一些JVAM將該載入器實現為一個以上的類載入器,或者它完全不可見;
- System:系統載入器,該載入器通常使用CLASSPATH環境變數來初始化。但是標準的Tomcat 5啟動指令碼(<CATALINA_HOME>/bin/catalina.sh或者<CATALINA_HOME>/bin/catalina.bat>)完全忽略了CLASSPATH環境變數的內容,並使用下述庫來構建System類載入器。如下:
從可以看出,Tomcat使用的CLASSPATH並非我們先前配置的目錄。
<CATALINA_HOME>/bin/bootstrap.jar:包含初始化Tomcat 5伺服器的main()方法和它所依賴的類載入器實現;
<JAVA_HOME>/lib/tools.jar:包含" javac "編譯器用來將JSP頁面轉化為servlet類;
<CATALINA_HOME>/bin/commons-logging-api-x.y.z.jar:包含commons logging API;
<CATALINA_HOME>/bin/commons-daemon.jar:包含commons daemon API;
jmx.jar :包含JMX 1.2實現。
- Common:該類載入器包含一些對Tomcat內部類和web應用可見的額外類。其中包括(1)jasper-compiler.jar:JSP 2.0編譯器(2)jsp-api.jar:JSP 2.0 API(3)servlet-api.jar:servlet 2.4 API等等。
- Catalina:該載入器初始化用來包含實現Tomcat 5本身所需要所有類和資源;
- Shared:在所有的web應用程式間共用的類和資源;
- WebappX:為每個部署在單個Tomcat 5執行個體上的Web應用建立的類載入器。載入/WEB-INF/classes和WEB-INF/lib下的類和資源。
值得注意的是,Web應用程式類載入器行為與預設的Java 2委派模型不同。當一個載入類的請求被WebappX類載入器處理時,類載入器將首先查看本地庫,而非在查看前就委派,但是也有例外,作為JRE基本類一部分的類不能被覆蓋,但是對與一些類,可以使用J2SE 1.4的Endorsed Standards Override機制。最後,任何包含servlet API的JAR包都將被該類載入器忽略。Tomcat 5所有其它的類載入器遵循常用的委派模式。具體細節請參見Tomcat
5的參考文檔。