1. 程式人生 > >Servlet類裝載器

Servlet類裝載器

一.類裝載器

Java虛擬機器使用每一個類的第一件事情就是將類的位元組碼裝載進來,裝載類位元組碼是由類裝載器完成的。類裝載器首先將一個類轉換成一個.class檔案,然後讀取檔案的內容,.class檔案的內容是utf-8編碼的,轉換成Unicode編碼後裝載入Java虛擬機器,當一個類被載入後,Java虛擬機器將其編譯為可執行的程式碼儲存在記憶體中,索引資訊儲存進HashTable中,索引關鍵字為類的完整名稱,當Java虛擬機器要使用某個類時,直接在這個HashTable中找,找不到則載入。載入一個類實際上實在建立一個Class的物件,這個物件封裝的記憶體就是當前載入的類的位元組碼資料,有以下3種方式獲得Class物件:

  • 類名.class
  • 物件.getClass
  • Class.forName("類名")

(1)類裝載器本身也是一個Java類,所以需要被其他類裝載器裝載。最頂層的裝載器為Bootstrap類裝載器,它是用特定與作業系統的原生代碼實現的,不用其餘的裝載器裝載,它負責載入Java核心包的類。Java核心包的類有2個類裝載器:ExtClassLoader和AppClassLoader。ExtClassLoader負責載入<JAVA_HOME>/jre/lib/ext目錄下的類,AppClassLoader負責載入應用程式的啟動執行類。

(2)一個類裝載器例項化時必須指定一個父裝載器,如果不指定。則以ClassLoader.getSystemClassLoader()方法返回的系統類裝載器為父裝載器,通常設定為AppClassLoader,是在第一次使用getSystemClassLoader()時設定的,呼叫發生在應用程式啟動的早期階段。可以通過java.system.class.loader來設定為其他類裝載器。ExtClassLoader是AppClassLoader的父級類裝載器,自身沒有父級類裝載器

。每個裝載器只能裝載特定目錄的類,但ClassLoader是一種委託模式裝載的,子裝載器可以呼叫父裝載器去裝載類,一直到追溯到沒有父級類裝載器為止,則使用Java虛擬機器的BootStarp裝載器裝載。若父裝載器無法裝載,則一級一級返回,如果最底層子裝載器無法裝載,則報告ClassNotFoundException。一個類裝載器只能建立某一個類的一個Class物件,但每個類裝載器存在不同的名稱和空間,可以分別給同一個類創建出Class物件,但這些Class物件沒有任何關聯。採用委託模式可以避免這種情況發生。

(3)如果在A類物件中New了B類物件,則Java虛擬機器使用載入A類的載入器載入B類。如果使用Class.forName載入,可以指定類載入,如果沒有指定,則為載入當前類的載入器載入。

(4)每個執行的執行緒都有一個關聯的上下文類裝載器。可以使用Thread.setContextClassLoader()方法設定上下文類載入器,預設為其父執行緒的上下文類載入器。主執行緒的類載入器初始化為ClassLoader.getSystemClassLoader()返回的載入器。一樣採用委託模式載入,如果父載入器無法載入,則自己進行載入。

2.Tomcat中的類裝載器

類裝載器的父子關係圖如下:

  • (1)Bootstrap是虛擬機器內嵌的裝載器和ExtClassLoader的總稱
  • (2)System通常為AppClassLoader,載入CLASSPATH環境變數中的類
  • (3)Commen載入<CATALINA_HOME>/commen/classes和<CATALINA_HOME>/commen/lib中的類,對Tomcat服務核心和每個Web應用程式都可見
  • (4)Catalina負責<CATALINA_HOME>/server/classes和<CATALINA_HOME>/server/lib,只對Tomcat伺服器核心可見
  • (5)Shared負責<CATALINA_HOME>/share/classes和<CATALINA_HOME>/share/lib,對所有Web程式可見,對Tomcat核心不可見
  • (6)Webapp負責當前Web程式/Web-INF/classes中的.class檔案和/Web-INF/lib中的jar包,只對當前Web程式可見。
  •  
  •