tomcat 學習筆記之 載入器

一、標準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

  •  引導啓動java 虛擬機

擴展類載入器(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 類(載入器類)

該類設計考慮了優化和安全兩個方案

  • 緩存以前已經載入的類來提高性能(緩存加載失敗的類,下次訪問直接拋異常)

安全性

  • 不容許載入某些類,寫入triggers 變量

  • 委託給系統類載入器

(1)類緩存

  • 爲了達到更好的性能,會緩存已載入的類

能夠是本地緩存

  • ClassLoader 維護一個Vector 對象,保存已載入的類,防止其被當垃圾回收

WebAppClassLoader 載入的類都是爲資源(org.apache.catalina.ResourceEntry的實例)

該實例會保存

  • class文件字節流
  • 最後修改時間
  • Manifest信息(若是來自 jar文件的話)

  • 已緩存類會存儲在一個叫resourceEntries的hashMap 中,key爲載入資源名稱

(2)載入類

遵照如下規則

  • 因爲全部類都已緩存,先檢查本地緩存
  • 本地緩存沒有檢查上一層緩存(即ClassLoader 類的 findLoadedClass 方法)
  • 兩者都沒有使用系統類載入器載入(防止web應用程序的類覆蓋javaee的類)
  • 若啓用了SecurityManager ,檢查是否容許載入該類;若是不容許,拋出 ClassNotFoundException
  • 打開delegate 標誌位,或者帶載入的類屬於包觸發器的包名,使用父載入器載入,(父爲空,使用系統載入器)
  • 從當前倉庫中載入相關類
  • 當前倉庫沒有,且標誌位delegate 關閉,使用父載入器載入,(父爲空,使用系統載入器)
  • 仍未找到拋出ClassNotFoundException
相關文章
相關標籤/搜索