1. 程式人生 > >web容器類載入順序

web容器類載入順序

 

Weblogic中classloader是分層次的,它只能載入比它層次高的類及它自身的類,同層次的類及比它層次低的類都不能載入。

在weblogic中的classloader有5個層次,從高到低排:
a. jdk
b. jdk ext
c. system classpath
d. ( APP-INF/classes  and  APP-INF/lib )
e. ( WEB-INF/classes and WEB-INF/lib )
    注意:這裡是先載入classes中的類,再載入lib中的類, 若要修改它的載入順序,可以通過在Weblogic.xml(版本為8)中加入以下程式碼:
    <container-descriptor>
       <prefer-web-inf-classes> true </prefer-web-inf-classes>
    </container-descriptor>

f. ejb.jar

注意:e 和 f 的classloader是同級的。
所以APP-INF/lib和APP-INF/classes下類不能例項化webapp下的類,這點尤其要注意,否則會報類找不到的錯誤。

來自Weblogic官方的說明檔案中,對於Weblogic的類載入順序給出了一個比較清晰和簡單的描述:

 當部署一個應用的時候,weblogic server會自動建立一個具有層次結構的類裝載器。
  1、a.Application Classloader負責裝載應用中的所有的EJB JAR檔案;
  2、b.Web Application Classloader負責裝載所有的Web application 中的WAR 檔案(所有得jsp檔案除外);
  3、c.Jsp Classloader 負責裝載Web application 中的所有的jsp 檔案。


    Tomcat與Weblogic是相反的:對於執行在 Java EE 容器中的 Web 應用來說,類載入器的實現方式與一般的 Java 應用有所不同。不同的 Web 容器的實現方式也會有所不同。以 Apache Tomcat 來說,每個 Web 應用都有一個對應的類載入器例項。該類載入器也使用代理模式,所不同的是它是首先嚐試去載入某個類,如果找不到再代理給父類載入器。這與一般類載入器的順序是相反的。這是 Java Servlet 規範中的推薦做法,其目的是使得 Web 應用自己的類的優先順序高於 Web 容器提供的類。這種代理模式的一個例外是:Java 核心庫的類是不在查詢範圍之內的。這也是為了保證 Java 核心庫的型別安全。

附:java類載入順序

java類裝載器 
  Java中的類裝載器實質上也是類,功能是把類載入jvm中,值得注意的是jvm的類裝載器並不是一個,而是三個,層次結構如下: 
  Bootstrap Loader - 負責載入系統類 
  | 
  - - ExtClassLoader - 負責載入擴充套件類 
  | 
  - - AppClassLoader - 負責載入應用類 
  為什麼要有三個類載入器,一方面是分工,各自負責各自的區塊,另一方面為了實現委託模型,下面會談到該模型
 
類載入器之間是如何協調工作的 
  前面說了,java中有三個類載入器,問題就來了,碰到一個類需要載入時,它們之間是如何協調工作的,即java是如何區分一個類該由哪個類載入器來完成呢。 
在這裡java採用了委託模型機制,這個機制簡單來講,就是“類裝載器有載入類的需求時,會先請示其Parent使用其搜尋路徑幫忙載入,如果Parent 找不到,那麼才由自己依照自己的搜尋路徑搜尋類”,注意喔,這句話具有遞迴性。
下面舉一個例子來說明,為了更好的理解,先弄清楚幾行程式碼: 
Public class Test{ 
  Public static void main(String[] arg){ 
  ClassLoader c = Test.class.getClassLoader(); //獲取Test類的類載入器 
  System.out.println(c);  
  ClassLoader c1 = c.getParent(); //獲取c這個類載入器的父類載入器 
  System.out.println(c1); 
  ClassLoader c2 = c1.getParent();//獲取c1這個類載入器的父類載入器 
  System.out.println(c2); 
  } 

把以上程式碼存到d:\my 資料夾下,直接編譯,然後在dos模式下執行 
D:\my\java Test 
  。。。AppClassLoader。。。 
  。。。ExtClassLoader。。。 
  Null 

D:\my 

注: 。。。表示省略了內容 
可以看出Test是由AppClassLoader載入器載入的 
AppClassLoader的Parent 載入器是 ExtClassLoader 

但是ExtClassLoader的Parent為 null 是怎麼回事呵,朋友們留意的話,前面有提到Bootstrap Loader是用C++語言寫的,依java的觀點來看,邏輯上並不存在Bootstrap Loader的類實體,所以在java程式程式碼裡試圖打印出其內容時,我們就會看到輸出為null。

弄明白了上面的示例,接下來直接進入類裝載的委託模型例項,寫兩個檔案,如下: 
檔案:Test1.java 
Public class Test1{ 
  Public static void main(String[] arg){ 
  System.out.println(Test1.class.getClassLoader()); 
  Test2 t2 = new Test2(); 
  T2.print(); 
  } 

檔案: Test2.java 
Public class Test2{ 
  Public void prin(){ 
  System.out.println(this.getClass().getClassLoader()); 
  } 

這兩個類的作用就是打印出載入它們的類裝載器是誰, 將這兩個檔案儲存到d:\my目錄下,編譯後,我們在複製兩份,分別置於jdk1.4\jre\classes下(注意,剛開始我們的系統下沒有此目錄,需自己建立) 與 jdk1.4\jre\lib\ext\classes下(同樣注意,開始我們的系統下也沒此目錄,手工建立), 然後切換到d:\my目錄下開始測試, 

測試一: 
<JRE所在目錄>\classes下 
Test1.class 
Test2.class 

<JRE所在目錄>\lib\ext\classes下 
Test1.class 
Test2.class 

D:\my下 
Test1.class 
Test2.class 


dos下輸入執行命令,結果如下: 
D:\my>java Test1 
Null 
Null 

D:\my> 
   
  從輸出結果我們可以看出,當AppClassLoader要載入Test1.class時,先請其Parent,也就是ExtClassLoader來載入,而ExtclassLoader又請求其Parent,即Bootstrap Loader來載入Test1.class. 由於 <JRE所在目錄>\Classes目錄為Bootstrap Loader的搜尋路徑之一,所以Bootstrap Loader找到了Test1.class,因此將它載入,接著在Test1.class之內有載入Test2.class的需求,由於Test1.class是由Bootstrap Loader所載入,所以Test2.class內定是由Bootstrap Loader根據其搜尋路徑來找,因Test2.class也位於Bootstrap Loader可以找到的路徑下,所以也被載入了,最後我們看到Test1.class與Test2.class都是由Bootstrap Loader(null)載入。 


測試二: 
<JRE所在目錄>\classes下 
Test1.class 

<JRE所在目錄>\lib\ext\classes下 
Test1.class 
Test2.class 

D:\my下 
Test1.class 
Test2.class 

dos下輸入執行命令,結果如下: 
D:\my>java Test1 
Null 
Exception in thread “main” java.lang.NoClassdefFoundError:Test2 at Test1.main。。。 
D:\my> 

  從輸出結果我們可以看出,當AppClassLoader要載入Test1.class時,先請其Parent,也就是ExtClassLoader來載入,而ExtclassLoader又請求其Parent,即Bootstrap Loader來載入Test1.class. 由於 <JRE所在目錄>\Classes目錄為Bootstrap Loader的搜尋路徑之一,所以Bootstrap Loader找到了Test1.class,因此將它載入,接著在Test1.class之內有載入Test2.class的需求,由於Test1.class是由Bootstrap Loader所載入,所以Test2.class內定是由Bootstrap Loader根據其搜尋路徑來找,但是因為Bootstrap Loader根本找不到Test2.class(被我們刪除了),而Bootstrap Loader又沒有Parent,所以無法載入Test2.class.最後我們看到Test1.class是由Bootstrap Loader(null)載入,而Test2.class則無法載入 


測試三 
<JRE所在目錄>\classes下 

Test2.class 

<JRE所在目錄>\lib\ext\classes下 
Test1.class 
Test2.class 

D:\my下 
Test1.class 
Test2.class 

dos下輸入執行命令,結果如下: 
D:\my>java Test1 
。。。ExtClassLoader。。。 
Null 

D:\my> 

  從輸出結果我們可以看出,當AppClassLoader要載入Test1.class時,先請其Parent,也就是ExtClassLoader來載入,而ExtclassLoader又請求其Parent,即Bootstrap Loader來載入Test1.class.但是Bootstrap Loader無法在其搜尋路徑下找到Test1.class(被我們刪掉了),所以ExtClassLoader只得自己搜尋,因此ExtClassLoader在其搜尋路徑 <JRE所在目錄>\lib\ext\classes下找到了Test1.class,因此將它載入,接著在Test1.class之內有載入Test2.class的需求,由於Test1.class是由ExtClassLoader所載入,所以Test2.class內定是由ExtClassLoader根據其搜尋路徑來找,但是因為ExtClassLoader有Parent,所以先由Bootstrap Loader幫忙尋找,Test2.class位於Bootstrap Loader可以找到的路徑下,所以被Bootstrap Loader載入了.最後我們看到Test1.class是由ExtClassLoader載入,而Test2.class則是由Bootstrap Loader(null)載入 

最後,總結一下,在Weblogic服務啟動的過程中,自動形成一個具有層次結構的類裝載器,首先裝載jdk及java擴充套件jar包或類;然後再載入Weblogic本身使用的各個jar包或類;然後再載入Web應用資料夾裡面的classes下的類,然後再載入Web應用資料夾裡面lib下的jar包或類。也就是說,每個層次的類裝載器均對應不同的類路徑,它們是一一對應的。 比如System裝載器對應著jdk及擴充套件路徑;Application裝載器對應著Weblogic的相關類;而web 應用裝載器對應著webapp應用下的classes和lib下的路徑;而jsp裝載器則對應著jsp檔案。

    當然,在載入過程中,若在高層次的載入器中已經載入了某類,那麼再以後的載入中,再次遇到該類也不會載入,只是會忽略。載入完成之後,將類放入Cache中供系統應用呼叫。

    在系統的執行過程中,若遇到使用該類的情況,則會遵循先通過其父類載入器進行載入的原則,比方說,我要載入一個WSWordManager類,
則系統會首先在Cache中尋找,若找不到,則呼叫父裝載器到與之對應的路徑裡面去尋找,一直向上,找著了則進行載入,若找不著則報出ClassNotFound的異常。

理解為:

1. weblogic會一次性裝載所有類,從上層到下層依次裝載所以上層不能例項化下層的類。

2. java會請示其Parent使用其搜尋路徑幫忙載入,如果Parent 找不到,那麼才由自己依照自己的搜尋路徑搜尋類

3.tomcat會從自己的搜尋路徑中搜索類,找不到再請示器parent

相關推薦

web容器載入順序

  Weblogic中classloader是分層次的,它只能載入比它層次高的類及它自身的類,同層次的類及比它層次低的類都不能載入。 在weblogic中的classloader有5個層次,從高到低排: a. jdk b. jdk ext c. system classpa

web.xml檔案載入順序 一、 1 、啟動一個 WEB 專案的時候, WEB 容器會去讀取它的配置檔案 web.xml ,讀取 和

web.xml 中的listener、 filter、servlet 載入順序及其詳解 一、概述 1、啟動一個WEB專案的時候,WEB容器會去讀取它的配置檔案web.xml,讀取<listener>和<context-param>兩個結點。 

web.xml檔案載入順序

web.xml 中的listener、 filter、servlet 載入順序及其詳解 一、概述 1、啟動一個WEB專案的時候,WEB容器會去讀取它的配置檔案web.xml,讀取<listener>和<context-param>兩個結點。  2、緊急著

web.xml的載入順序和過程

Web.xml配置詳解之context-param <context-param> <param-name>contextConfigLocation</param-name> <param-value>contextConfigLocat

Java載入順序問題

測試java程式碼塊中靜態塊,初始塊,構造塊的執行順序。 定義三個類A,B,C,B繼承於A,C繼承於B。 程式碼如下: package 類載入問題; public class A { static{ System.out.print("A類靜態塊1 "); } { Sys

使用@Order註解調整配置載入順序

1 、@Order    1、Spring 4.2 利用@Order控制配置類的載入順序,    2、Spring在載入Bean的時候,有用到order註解。    3、通過@Order指定執行順序,值越小,越先執行 &

載入順序說明

在 Java 中,Class<T> 和 ClassLoader 是造物之始。 萬物皆是“某類T” 的存在物,而“某類T” 是“萬類之類 Class<T>” 的存在物,類別也是一種存在物,存在物即 Object。 例項 t -> 類別 T -&

初探spring applicationContext在web容器載入過程

首先從WEB.XML入手 ==>web.xml <context-param> <param-name>webAppRootKey</param-nam

Java中static關鍵字解析以及載入順序例題

一.static關鍵字的用途 在《Java程式設計思想》P86頁有這樣一段話:   “static方法就是沒有this的方法。在static方法內部不能呼叫非靜態方法,反過來是可以的。而且可以在沒有建立任何物件的前提下,僅僅通過類本身來呼叫static方法

Tomcat6載入器定義(class載入順序)

Class Loader Definitions As indicated in the diagram above, Tomcat 6 creates the following class loaders as it is initialized: (譯:就像上面

Java相同全限定名的載入順序

相同的類指:類的全限定名一樣 問題: 怎麼優先載入自己寫的類 1. 解析:  class檔案所在位置, 直接在classpath下, 在jar包中  a: 相同的類, 一個在web-inf/classes目錄下, 一個在jar包中: 此時優先載入classes目錄下

Java靜態程式碼塊和靜態方法的區別/載入順序

 (一)java 靜態程式碼塊 靜態方法區別  一般情況下,如果有些程式碼必須在專案啟動的時候就執行的時候,需要使用靜態程式碼塊,這種程式碼是主動執行的;需要在專案啟動的時候就初始化,在不建立物件的情況下,其他程式來呼叫的時候,需要使用靜態方法,這種程式碼是被動執行的.

Web容器載入過程

(一)過程1.0啟動web專案的時候。  web容器讀取web.xml檔案,<listener>和<context-param>兩個節點。2.0 接著,容器建立一個ServletContext(sevlet上下文),這個web專案的所有部分都將共享這個

java複習一 ——java web專案啟動載入順序

 web.xml載入過程(步驟):        1.啟動WEB專案的時候,容器(如:Tomcat)會去讀它的配置檔案web.xml.讀兩個節點:       <listener></listener> 和 <context-param&g

Tomcat目錄結構以及載入順序

Tomcat是一個優秀的Servlet容器,本身使用java語言編寫。Tomcat是Apache開源軟體組織的一個軟體專案。Tomcat執行穩定、可靠,而且有著開源的優勢,Tomcat已成為目前企業開

載入順序

目錄 一、類載入做了哪些事?   之前沒有進行類載入  1.類載入,同時初始化類中靜態的屬性(賦預設值)  2.執行靜態程式碼塊  3.分配記憶體空間,同時初始化非靜態的屬性(賦預設值)  4.如果宣告屬性的同時有顯示的賦值,那麼進行顯示賦值把預設值覆蓋

載入順序,JVM角度分析理解,構造器方法以及例項構造器方法執行順序

今天先來分析一下經常遇到的一個問題,在筆試面試中可能會經常遇見,類中欄位程式碼塊的載入順序等,從jvm角度分析一下這個問題。我們先來看下知識點,接下來進行程式碼實踐驗證。 <clinit>,類構造器方法,在jvm第一次載入class檔案時呼叫,因為是類級別的,所

Tomcat 啟動時載入順序

Tomcat啟動時classloader載入順序   Tomcat的class載入的優先順序一覽     1.最先是$JAVA_HOME/jre/lib/ext/下的jar檔案。     2.環境變數CLASSPATH中的jar和class檔案。     3.$CATALINA_HOME/common/cla

web.xml配置載入順序context-param 、listener、 filter、servlet

<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:x

SpringMVC 專案啟動的載入順序(一)父容器的啟動

最近在研究Spring MVC專案的啟動載入順序,做一個具體說明:一、web容器的啟動1、web專案啟動的時候,容器會優先讀取web.xml檔案,並且先找到<listener></listener>和<context-param></