一、標準web 應用程序的載入器,tomcat 中的載入器java
- servlet 容器須要實現一個自定義的載入器
- 因爲servlet 容器不能徹底信任運行的servlet 程序
- 使用系統類的載入器,則該類能夠訪問任何程序,包括本地虛擬機中環境變量classpath 指明的全部類,很是危險
- servlet 應該只容許載入WEB-INF/classes 目錄和WEB-INF/lib 目錄
- 在 Catalina 中,載入器是 org.apache.catalina.Loader 接口的實例
實現一個自定義的載入器另外一個緣由程序員
- 提供自動重載功能
- WEB-INF/classes 目錄和WEB-INF/lib 目錄發生變化時,從新加載這些類
- 自動重載功能 實現org.apache.catalina.loader.Reloader 接口
二、java 的類載入器web
- 每次建立類實例,先將類加載到內存中
- 會在java核心類庫,以及classpath 變量中指明的目錄中掃描相關類
- 找不到拋異常:ClassNotFoundException
三、JVM 三種類載入器apache
- 引導類載入器(bootstrap class loader)
- 擴展類載入器(extension class loader)
- 系統類載入器(system class loader)
- --------------三個類是父子繼承關係,從上到下的順序
引導類載入器(bootstrap class loader)bootstrap
擴展類載入器(extension class loader)數組
- 載入標準擴展類目錄中的類(jdk/jre/lib/ext)
系統類載入器(system class loader)緩存
- 默認類載入器,搜索classpath指明的 路徑和jar文件
類載入器代理模型tomcat
- 按照從上到下的順序載入,優先級遞減
- 主要是爲了解決類載入過程當中的安全性問題
- 可使用安全管理器來限制某個類或路徑的訪問
- 舉例:某人在硬盤上寫上java.lang.Object 會被忽略,而不是覆蓋系統的Object類
繼承java.lang.ClassLoader 能夠實現本身的類載入器安全
tomcat之因此使用自定義類載入器緣由:app
- 爲了在載入類中指定某些規則
- 爲了緩存已經載入的類
- 爲了實現類的預載入,方便使用
四、Loader 接口
在載入web應用程序中須要servlet 類及其相關類時,須要遵照一些明確規則
- 應用程序的servlet 類只能部署在WEB-INF/classes 目錄下
- servlet 類不能訪問其餘路徑的類,即便這些類包含在當前tomcat jvm的classpath 路徑下
- servlet 類只能訪問 WEB-INF/lib 目錄下
tomcat 載入器指的是web 應用程序載入器
- 必須實現 org.apache.catalina.Loader 接口
- 實現中會使用 org.apache.catalina.WebappClassLoader
WEB-INF/classes 和WEB-INF/lib 做爲倉庫被添加到載入器中的
- addRepository 添加一個倉庫
- getRepository 獲取全部已添加倉庫數組對象
tomcat 載入器會和一個Context 級別容器關聯
- Context 中一個或多個類被修改了,loader 接口支持自動重載(程序員不須要重啓tomcat)
- loader 接口使用 modified方法自動重載
- 配置自動重載
載入器實現會指明,是否委託給一個父類載入器
具體實現中使用了org.apache.catalina.WebappClassLoader 繼承自 java.net.URLClassLoader
五、Reloader 接口
六、WebappLoader 類
- org.apache.catalina.WebappLoader 實現了 Loader 接口
- 其實例就是web 應用程序中的載入器
- 也實現了LifeCycle 接口,其相關聯的容器啓動和關閉
- 實現了 RunnerAble 接口
調用WebappLoader 的start 方法,會完成如下幾項重要工做:
- 建立一個類載入器
- 設置倉庫
- 設置類路徑
- 設置訪問權限
- 啓動一個新線程支持自我重載
(1)建立一個類載入器
- 私有字符串變量loaderClass 默認保存的是org.apache.catalina.WebappClassLoader
- 也能夠繼承WebappClassLoader,實現自定義類加載器(不繼承,會拋異常)
(2)設置倉庫
- 調用 setRepository 將WEB-INF/classes 目錄傳入類加載器addRepository
- WEB-INF/lib 目錄傳入類加載器 setJarPath
(3)設置類路徑
(4)設置訪問權限
- 啓用了安全管理器,使用setPermission 設置相關目錄訪問權限
(5)開啓新線程開啓類的從新載入
- WebappLoader 使用一個線程週期性掃描資源的時間戳(時間間隔是變量checkInterval 默認15秒)
七、WebappClassLoader 類(載入器類)
該類設計考慮了優化和安全兩個方案
- 緩存以前已經載入的類來提高性能(緩存加載失敗的類,下次訪問直接拋異常)
安全性
(1)類緩存
能夠是本地緩存
- ClassLoader 維護一個Vector 對象,保存已載入的類,防止其被當垃圾回收
WebAppClassLoader 載入的類都是爲資源(org.apache.catalina.ResourceEntry的實例)
該實例會保存
- class文件字節流
- 最後修改時間
- Manifest信息(若是來自 jar文件的話)
- 已緩存類會存儲在一個叫resourceEntries的hashMap 中,key爲載入資源名稱
(2)載入類
遵照如下規則
- 因爲全部類都已緩存,先檢查本地緩存
- 本地緩存沒有檢查上一層緩存(即ClassLoader 類的 findLoadedClass 方法)
- 兩者都沒有使用系統類載入器載入(防止web應用程序的類覆蓋javaee的類)
- 若啓用了SecurityManager ,檢查是否容許載入該類;若是不容許,拋出 ClassNotFoundException
- 打開delegate 標誌位,或者帶載入的類屬於包觸發器的包名,使用父載入器載入,(父爲空,使用系統載入器)
- 從當前倉庫中載入相關類
- 當前倉庫沒有,且標誌位delegate 關閉,使用父載入器載入,(父爲空,使用系統載入器)
- 仍未找到拋出ClassNotFoundException