<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    The NoteBook of EricKong

      BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
      611 Posts :: 1 Stories :: 190 Comments :: 0 Trackbacks

    概述

    Java Classloader長期以來一直是導致混亂的根源,并且隨著 Java 語言的發展變得比以往任何時候都更為復雜。隨著 J2EE 應用服務器的出現,Java Classloader的復雜性進一步增加了。現在,JVM 中的每個應用程序都可能有自己的Classloader層次,這將導致一個單獨的 JVM 可能包含許多的Classloader。而不同的J2EE應用服務器的Classloader的層次和策略也會有所差異,移植的復雜度也隨之上升。

    第一部分曾經提到:在移植的前期,我們應當分析系統的框架,澄清其中各個模塊之間的依賴關系(包括各個業務模塊之間的依賴關系,以及Web模塊和EJB模塊之間的依賴關系等),為了盡量避免模塊之間的交叉引用,我們甚至要重新打包。大家可能會問,我們的應用程序原本在WebLogic 、Tomcat、Jboss、Resin上能夠正常的運行,為什么我們要重新分析模塊之間的依賴關系,甚至重新打包呢?實際上,每個應用服務器都有著對于ClassLoader的不同實現。由于這些ClassLoader在裝載類文件時的行為會有所差異,所以如果應用程序未經重整和優化,很有可能在WebSphere應用服務器上運行失敗。然而,面臨這種差異,我們并不需要過多的恐慌。實際上,只要把握以下幾個原則,相信,交織在模塊依賴和類型裝載之中的問題,就可以迎刃而解了:

    一、 理解WebSphere ClassLoader的裝載層次和裝載策略

    二、 理清模塊間的依賴關系

    三、 將合適的裝載策略應用到各個模塊

    注意:我們并不需要了解WebLogic、Tomcat、JBoss、Resin等J2EE應用服務器的 Classloader的體系結構,只要我們理解了WebSphere的Classloader的體系結構,理清了應用程序的各個模塊之間的依賴關系,就可以解決由不同的J2EE應用服務器的Classloader的體系結構的差異給移植帶來的問題。

    首先我們簡單介紹一下WebSphere ClassLoader的體系結構,詳細內容可參看參考文檔。


    圖一、WebSphere Classloader層次結構圖
    圖一、WebSphere Classloader層次結構圖

    處于體系結構最上層的是系統 Classloader,它由bootstrap,extensions和 classpath三個classloader組成,bootstrap classloader會查找jre/lib下的類文件,從而加載核心類庫,extensions classloader使用系統屬性java.ext.dirs(通常是jre/lib/ext)查找和加載類文件,classpath classloader使用操作系統的classpath環境變量來查找和加載類文件。

    處于體系結構第二層的是WebSphere Extensions Classloader,它被用于裝載WebSphere的運行時類庫、J2EE類庫以及用戶代碼。它使用系統屬性ws.ext.dirs(通常是%was_root%\classes,%was_root%\lib和%was_root%\lib\ext)查找和加載類文件。

    處于體系結構第三層的是Application Classloader,用于加載EARs,RARs,JARs中的類文件。由于Application Classloader Policy是MULTIPLE,WebSphere應用服務器會為每一個EAR文件(EAR 1到EAR N)分配了一個Application Classloader。值得注意的是,如果WAR Classloader Policy如果設置為Application,那么Application Classloader可用于加載WARs中的類文件。

    處于體系結構最底層的是WAR Classloader,用于加載WAR文件中的類文件。圖中示意了WebSphere應用服務器為每一個WAR文件(WAR 1到 WAR N)分配了一個WAR Classloader的場景。值得注意的是,如果WAR Classloader Policy設置為MODULE,WebSphere應用服務器才會使用WAR Classloader加載WAR文件中的類文件。

      

    圖一中的單向箭頭表明了引用次序,即處于下面的Classloader可以調用其上層的類文件,而上層的Classloader無法調用其下面的類文件。這就為應用程序及其各個模塊的組織結構和設置Classloader策略提供了線索和限制。

    接下來,我們用一個實例來說明針對特定的模塊依賴關系應當如何設置WebSphere Classloader的裝載策略(policy)以及如何將各個模塊部署到合適的位置。

    有一個應用程序里有三個互相依賴的模塊,其調用關系如下:


    圖二、模塊關系圖
    圖二、模塊關系圖

    其中,WAR模塊中的SampleServlet類調用了UTILITY模塊中SampleUtility類,如代碼一所示:


    代碼一、SampleServlet.java
    public class SampleSevlet extends HttpServlet implements Servlet {
    	public void doGet(HttpServletRequest req, HttpServletResponse resp)
    		throws ServletException, IOException {
    		System.out.println("SampleServlet invokes SampleUtility");
    		new SampleUtility().callSampleSessionBean();
    	}
    	public void doPost(HttpServletRequest req, HttpServletResponse resp)
    		throws ServletException, IOException {
    	}
    }
    

    UTILITY模塊中SampleUtility類調用了EJB模塊中的SampleSessionBean類(通過callSampleSessionBean方法),如代碼二所示:


    代碼二、SampleUtility.java
    public class SampleUtility {
    public void callSampleSessionBean() {
    	 try{
    	     Context initCtx = new InitialContext();
    	     Object result = initCtx.lookup("ejb/sample/SampleSessionHome");
    	     SampleSessionHome ssh = (SampleSessionHome)
    PortableRemoteObject.narrow(
    					  result, SampleSessionHome.class);
    SampleSession ss = ssh.create();
    	     System.out.println("SampleUtility invokes SampleSessionBean");
    	     ss.callSampleUtility();
    	 }catch(Exception e){
    	     e.printStackTrace();
    	 }
    }
    public void finish() {
    	 System.out.println("The process has been finished");
    }
    }
    

    SampleSessionBean類又調用了UTILITY模塊中的SampleUtility類,如代碼三所示:


    代碼三、SampleSessionBean.java
    public class SampleSessionBean implements javax.ejb.SessionBean {
    	private javax.ejb.SessionContext mySessionCtx;
    	public javax.ejb.SessionContext getSessionContext() {
    		return mySessionCtx;
    	}
    	public void setSessionContext(javax.ejb.SessionContext ctx) {
    		mySessionCtx = ctx;
    	}
    	public void ejbCreate() throws javax.ejb.CreateException {
    	}
    	public void ejbActivate() {
    	}
    	public void ejbPassivate() {
    	}
    	public void ejbRemove() {
    	}
    	public void callSampleUtility() {
    		System.out.println("SampleSessionBean invokes SampleUtility");
    		new SampleUtility().finish();
    	}
    }
    

    這三個類之間的調用關系如下圖所示:


    圖三、順序圖

    下面我們通過不同的部署策略來深入探討WebSphere Classloader是如何影響應用程序運行的。1、如果將Utility模塊(JAR文件)拷貝到Web 模塊的 WEB-INF/lib 文件夾中,那么,Utility模塊將會被視為War模塊的一部分,如圖所示:


    圖四、Utility模塊(JAR文件)在Web 模塊中
    圖四、Utility模塊(JAR文件)在Web 模塊中

    如果我們將WAR Classloader Policy設置為MODULE(默認設置),如圖五所示:


    圖五、WAR Classloader Policy設置
    圖五、WAR Classloader Policy設置
    • 那么WebSphere應用服務器會使用WAR Classloader來裝載WAR模塊的類文件。而EJB模塊始終是通過Application Classloader進行裝載,由于Application Classloader處于WAR classloader的上層,EJB模塊無法引用War模塊的類文件。這樣,當SampleSessionBean調用SampleUtility時,會拋出異常:

      SystemOut     O SampleServlet invokes SampleUtility
      SystemOut     O SampleUtility invokes SampleSessionBean
      SystemOut     O SampleSessionBean invokes SampleUtility
      

      ExceptionUtil E CNTR0020E: 在 bean"BeanId(Sample#SampleEJB.jar#SampleSession, null)"上處理方法"callSampleUtility"時發生非應用程序異常。異常數據:

      java.lang.NoClassDefFoundError: sample/SampleUtility
      at sample.SampleSessionBean.callSampleUtility(SampleSessionBean.java:41)
    • 如果我們將WAR Classloader Policy設置為APPLICATION,那么WebSphere應用服務器會使用Application Classloader來裝載WAR模塊和EJB模塊的類文件。由于兩個模塊使用了相同的Classloader進行裝載,所以兩個模塊間的類可以相互引用應用服務器輸出的結果如下:

      SystemOut     O SampleServlet invokes SampleUtility
      SystemOut     O SampleUtility invokes SampleSessionBean
      SystemOut     O SampleSessionBean invokes SampleUtility
      SystemOut     O The process has been finished

    2、如果將Utility模塊拷貝到%was_root%\lib\ext , Websphere應用服務器會使用WebSphere Extensions Classloader加載Utility模塊中的類文件,由于WebSphere Extensions Classloader處于Application classloader和WAR classloader的上層,所以SampleServlet和SampleSessionBean可以引用到SampleUtility,但是SampleUtility引用不到SampleSessionBean,因此,當SampleUtility調用SampleSessionBean時會拋出異常。

    上面講的配置方法比較適合將已經開發完的J2EE應用程序按照原有的包結構部署到WebSphere上,但有的項目可能會在開發完部分子系統的時候,就要將J2EE應用程序遷移到WebSphere上,然后,在WSAD中繼續開發未完成的子系統。這樣,把UTILITY模塊打包到WAR模塊的WEB-INF/lib 文件夾中,將使得開發公用類變得繁瑣。幸運的是,WSAD提供了一個方式使公用類的開發和調試方法變得簡單、清晰。

    我們還用上面的實例進行演示。

    首先,我們要為UTILITY模塊創建一個JAVA項目。然后將utility.jar中的SampleUtility.java導入到此JAVA項目(頁可以稱作實用程序項目)當中。創建項目的結果如下圖所示:


    圖六、實用程序項目
    圖六、實用程序項目

    然后,將此實用程序項目添加到應用程序部署描述符當中,如圖七所示:

    1、 選擇"Sample"項目中的"應用程序部署描述符";

    2、 選擇"模塊";

    3、 在"項目實用程序JAR欄目中"點擊"添加";

    4、 選擇"Utility"項目,點擊"完成"。


    圖七、應用程序部署描述符
    圖七、應用程序部署描述符

    在所有依賴于此模塊的項目中,添加JAR模塊依賴項(主要包括EJB模塊和WEB模塊):

    1、在EJB模塊和WEB模塊分別編輯MANIFEST.MF文件,雙擊MANIFEST.MF文件可打開可視化編輯器編輯此文件


    圖八、MANIFEST.MF文件
    圖八、MANIFEST.MF文件

    2、 在EJB模塊的MANIFEST.MF文件中選擇Utility.jar


    圖九、EJB模塊的MANIFEST.MF文件
    圖九、EJB模塊的MANIFEST.MF文件

    3、 在WEB模塊的MANIFEST.MF文件中選擇Utility.jar


    圖十、WEB模塊的MANIFEST.MF文件
    圖十、WEB模塊的MANIFEST.MF文件

    接下來,我們可以啟動應用服務器,對SampleServlet進行測試,控制臺的顯示結果如下:

    SystemOut     O SampleServlet invokes SampleUtility
    SystemOut     O SampleUtility invokes SampleSessionBean
    SystemOut     O SampleSessionBean invokes SampleUtility
    SystemOut     O The process has been finished

    posted on 2011-12-27 16:06 Eric_jiang 閱讀(697) 評論(0)  編輯  收藏 所屬分類: Java
    主站蜘蛛池模板: 亚洲精品午夜国产va久久| 国产AV无码专区亚洲精品| 中国china体内裑精亚洲日本| 久久青草免费91观看| 国产亚洲成av人片在线观看 | 国产av无码专区亚洲av桃花庵| 国产精品极品美女自在线观看免费| 亚洲精品无码久久久| 特级av毛片免费观看| 亚洲AV无码一区二区三区在线观看| 国产精品亚洲а∨无码播放不卡 | 亚洲成a人在线看天堂无码| 黄床大片30分钟免费看| 亚洲视频在线精品| 国产精成人品日日拍夜夜免费| 无码欧精品亚洲日韩一区| 国产成人精品免费视| 亚洲欧美一区二区三区日产| 国产美女a做受大片免费| 一区视频免费观看| 亚洲国产一区二区三区青草影视 | 亚洲国产成人九九综合| 永久免费毛片在线播放| 国产成人精品亚洲| 国产亚洲高清不卡在线观看| 一级毛片**不卡免费播| 日本亚洲色大成网站www久久| 国产三级免费电影| 黄网站免费在线观看| 亚洲人成激情在线播放| 亚洲国产精品毛片av不卡在线| 免费无码作爱视频| 日韩亚洲不卡在线视频中文字幕在线观看| 免费jlzzjlzz在线播放视频| 国产偷伦视频免费观看| 亚洲人成77777在线播放网站不卡| 国产一卡二卡≡卡四卡免费乱码| 永久免费A∨片在线观看| 亚洲天堂2017无码中文| 国产亚洲大尺度无码无码专线 | 亚洲精品麻豆av|