一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

openFire 源碼解讀

 hehffyy 2013-12-27

1.openfire的入口main文件在src/java 文件夾下的org.jivesoftware.openfire.starter包中。

2.運(yùn)行main函數(shù)之后openfire會(huì)調(diào)用start方法,首先是獲取到ClassLoader對(duì)象。那么什么是ClassLoader對(duì)象呢?

下面具體學(xué)習(xí)ClassLoader的知識(shí)。

  1. 首先ClassLoader作用是加載Class文件到j(luò)vm中,供程序使用,java程序可以動(dòng)態(tài)加載類定義,這個(gè)動(dòng)態(tài)加載的機(jī)制就是通過ClassLoader來實(shí)現(xiàn)的。

  2. ClassLoader 是加載Class文件的(ExtClassLoader和AppClassLoader也在此時(shí)被加載),那么ClassLoader又被誰加載呢?是一 個(gè)被不是java語言所編寫的ClassLoader來加載的,這個(gè)ClassLoader就是bootstrapClassLoader(啟動(dòng)類加載 器)。這個(gè)加載器在jvm運(yùn)行的時(shí)候加載java核心的api以滿足java程序最基本的需求。其中包括用戶定義的ClassLoader,用戶定義的 ClassLoader就是通過程序創(chuàng)建的ClassLoader,那么也有非程序員創(chuàng)建的ClassLoader,就是jvm自己提供的吧(這句是自己 理解的)。用戶自定義的ClassLoader有ExtClassLoader,ExtClassLoader加載java的擴(kuò)展的api,也就是 /lib/ext中的類。用戶自定義的ClassLoader還有AppClassLoader,AppClassLoader用戶機(jī)器上的 CLASSPATH設(shè)置目錄中的Class的,通常在沒有指定ClassLoader的情況下,程序自定義的類由AppClassLoader加載

  3. ClassLoader 的加載模式:雙親委托模式進(jìn)行加載。該模式的原理是:某個(gè)自定義的ClassLoader加載Class的時(shí)候都會(huì)先委托他的parnet ClassLoader加載該Class,當(dāng)parent ClassLoader加載失敗,再由當(dāng)前的ClassLoader加載該Class,但是如果該ClassLoader的parent ClassLoader為null那么該ClassLoader的parent就是bootstrapClassLoader。

  4. 使用雙親委托模式的優(yōu)點(diǎn)是:

    第一:避免重復(fù)加載,當(dāng)父親已經(jīng)加載了該類,那么子ClassLoader就沒有必要加載該class了。

    第二:安全因素。

     

3.獲取當(dāng)前類的類類加載器的方法:

  1. <span style="background-color:rgb(51,153,102)">public ClassLoader findParentClassLoader(){   
  2. //獲取父類加載器   
  3.     ClassLoader parent = Thread.currentThread().getContextClassLoader();   
  4. if(parent==null){   
  5.     parent = this.getClass().getClassLoader();   
  6.     if(parent==null){   
  7.         parent = ClassLoader.getSystemClassLoader();   
  8. }   
  9. }   
  10. return parent;   
  11. }</span>  

4.類加載器的種類:

  •  bootstrap class Loader(引導(dǎo)類加載器) 用來加載java的核心類庫

  •  extensions class loader(擴(kuò)展類加載器) 用來加載java的擴(kuò)展庫Java 虛擬機(jī)的實(shí)現(xiàn)會(huì)提供一個(gè)擴(kuò)展庫目錄。該類加載器在此目錄里面查找并加載 Java 類[ExtClassLoader]

  • 系統(tǒng)類加載器(system class loader)Java 應(yīng)用的類都是由它來完成加載的??梢酝ㄟ^ ClassLoader.getSystemClassLoader() 來獲取它[AppClassLoader]

上一節(jié)主要學(xué)習(xí)了jvm的類加載器,這節(jié)繼續(xù)進(jìn)行,從org.jivesoftware.openfire.starter.ServerStarter文件的第72行進(jìn)行解讀。

System.getProperty("openfire.lib.dir");

上面這句話是什么意思呢,根據(jù)字面意思理解應(yīng)該是獲取到當(dāng)前項(xiàng)目也就是openfire的lib路徑

繼續(xù)往下讀,如果存放lib的路徑不存在那么就創(chuàng)建一個(gè)存放lib的文件夾

同樣的通過這個(gè)方法可以獲取到其他的屬性 如下列表

 

java.version

Java 運(yùn)行時(shí)環(huán)境版本

java.vendor

Java 運(yùn)行時(shí)環(huán)境供應(yīng)商

java.vendor.url

Java 供應(yīng)商的 URL

java.home

Java 安裝目錄

java.vm.specification.version

Java 虛擬機(jī)規(guī)范版本

java.vm.specification.vendor

Java 虛擬機(jī)規(guī)范供應(yīng)商

java.vm.specification.name

Java 虛擬機(jī)規(guī)范名稱

java.vm.version

Java 虛擬機(jī)實(shí)現(xiàn)版本

java.vm.vendor

Java 虛擬機(jī)實(shí)現(xiàn)供應(yīng)商

java.vm.name

Java 虛擬機(jī)實(shí)現(xiàn)名稱

java.specification.version

Java 運(yùn)行時(shí)環(huán)境規(guī)范版本

java.specification.vendor

Java 運(yùn)行時(shí)環(huán)境規(guī)范供應(yīng)商

java.specification.name

Java 運(yùn)行時(shí)環(huán)境規(guī)范名稱

java.class.version

Java 類格式版本號(hào)

java.class.path

Java 類路徑

java.library.path

加載庫時(shí)搜索的路徑列表

java.io.tmpdir

默認(rèn)的臨時(shí)文件路徑

java.compiler

要使用的 JIT 編譯器的名稱

java.ext.dirs

一個(gè)或多個(gè)擴(kuò)展目錄的路徑

os.name

操作系統(tǒng)的名稱

os.arch

操作系統(tǒng)的架構(gòu)

os.version

操作系統(tǒng)的版本

file.separator

文件分隔符(在 UNIX 系統(tǒng)中是“/”)

path.separator

路徑分隔符(在 UNIX 系統(tǒng)中是“:”)

line.separator

行分隔符(在 UNIX 系統(tǒng)中是“/n”)

user.name

用戶的賬戶名稱

user.home

用戶的主目錄

user.dir

用戶的當(dāng)前工作目錄

 

上一節(jié)我們閱讀到了org.jivesoftware.openfire.starter.ServerStarter文件中的第90行,這節(jié)繼續(xù)。

第90行調(diào)用unpackArchives(libDir, true);方法。

通過閱讀該方法的英文注釋大概意思是:轉(zhuǎn)換文件夾中的一些包文件為一個(gè)標(biāo)準(zhǔn)的jar文件,在轉(zhuǎn)換jar文件的同時(shí)每個(gè)被轉(zhuǎn)的包文件就會(huì)被刪除,如果包文件不存在,那么就什么都不做。

 

  • 過濾文件

帶著這句話我們進(jìn)行閱讀。該方法傳入了2個(gè)參數(shù),第一個(gè)是一個(gè)lib文件夾,第二個(gè)參數(shù)是個(gè)boolean值true。

 

  1. File [] packedFiles = libDir.listFiles(new FilenameFilter() {  
  2.     public boolean accept(File dir, String name) {  
  3.         return name.endsWith(".pack");  
  4.     }  
  5. });  
  6.                  
  7. if (packedFiles == null) {  
  8.     // Do nothing since no .pack files were found  
  9.     return;  
  10. }  

以上代碼是unpackArchives方法中的146到155行的代碼。

上面的第一句話我們大家應(yīng)該很熟悉,沒錯(cuò),這句話我也經(jīng)常用,但是我經(jīng)常用不帶參數(shù)的方法也就是一般這樣用,

 

File [] packedFiles = libDir.listFiles();


這樣是獲取到一個(gè)文件夾下的所有的文件。

而帶參數(shù)的根據(jù)字面意思大概是過濾文件名稱的意思,就是過濾一定規(guī)則的文件,而不是顯示所有的文件,

過濾用FilenameFilter這個(gè)接口,一般我們用接口都是通過繼承的方法來使用,但是我們現(xiàn)在通過new的方式來使用,其實(shí)這種用法還是蠻多的,比如很多注冊(cè)事件== 很多地方都大量運(yùn)用了該方法。

但是new接口的時(shí)候我們會(huì)發(fā)現(xiàn)我們就要實(shí)現(xiàn)里面所有的方法,少一個(gè)方法都不可以。因?yàn)?code class="java plain">FilenameFilter接口只有一個(gè)方法accept所以我們?cè)趎ew的同時(shí)就會(huì)實(shí)現(xiàn)該方法,我們通過該方法直接過濾以某種后綴名的文件就可以了現(xiàn)在我們要列出.pack類型的文件所以我們應(yīng)該寫 return name.endsWith(".pack");就可以獲取到了。很方便吧。

通過以上代碼我們學(xué)習(xí)一個(gè)知識(shí)點(diǎn),那就是獲取某個(gè)文件夾下的某種格式的文件列表應(yīng)該用FilenameFilter來實(shí)現(xiàn),實(shí)現(xiàn)方法是一下代碼

  1. File [] packedFiles = libDir.listFiles(new FilenameFilter() {  
  2.     public boolean accept(File dir, String name) {  
  3.         return name.endsWith(".pack");  
  4.     }  
  5. });  

如果沒有獲取到.pack類型的文件那么什么都不做,直接返回。

  • 具體實(shí)現(xiàn)把.pack的文件轉(zhuǎn)換為jar文件

    上面我們獲取到了.pack的文件數(shù)據(jù),然后開始遍歷該數(shù)組,把每個(gè).pack文件轉(zhuǎn)為jar文件。

    關(guān)鍵代碼如下

    1. <span style="background-color:rgb(153,204,0)">InputStream in = new BufferedInputStream(new FileInputStream(packedFile));  
    2. JarOutputStream out = new JarOutputStream(new BufferedOutputStream(  
    3.         new FileOutputStream(new File(libDir, jarName))));  
    4. Pack200.Unpacker unpacker = Pack200.newUnpacker();  
    5. // Print something so the user knows something is happening.  
    6. if (printStatus) {  
    7.     System.out.print(".");  
    8. }  
    9. // Call the unpacker  
    10. unpacker.unpack(in, out);  
    11.       
    12. in.close();  
    13. out.close();  
    14. packedFile.delete();  
    15. unpacked = true;</span>  

     

以上的packedFile是遍歷每個(gè).pack的文件。就這樣把.pack文件轉(zhuǎn)為了jar文件。

第三節(jié)中我們閱讀了org.jivesoftware.openfire.starter.ServerStarter文件到91行,繼續(xù)吧!

這節(jié)我們跳過108行之前的從108行開始學(xué)習(xí),91行到107行相對(duì)比較簡(jiǎn)單。

從第108行到113行主要做了2件事情

第一:加載系統(tǒng)用到的jar包跟zip包到classpath中

第二:通過反射加載org.jivesoftware.openfire.XMPPServer類文件。

 

一:那么如何加載文件到classpath中呢

  1. openfire用什么加載文件到classpath中:openfire中用org.jivesoftware.openfire.starter.JiveClassLoader加載文件到classpath中(該類是繼承了URLClassLoader)

  2. openfire加載文件到classpath的方法:

    首先找出jar跟zip類型的文件,代碼如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    File[] jars = libDir.listFiles(new FilenameFilter() {
        public boolean accept(File dir, String name) {?
            boolean accept = false;
            String smallName = name.toLowerCase();
            if (smallName.endsWith(".jar")) {
                accept = true;
            }
            else if (smallName.endsWith(".zip")) {
                accept = true;
            }
            return accept;
        }
    });

    然后調(diào)用父類URLClassLoader的addURL方法加載文件到classpath中,代碼如下

    1
    2
    3
    4
    5
    for (int i = 0; i < jars.length; i++) {
        if (jars[i].isFile()) {
            addURL(jars[i].toURI().toURL());
        }
    }

二:如何通過反射加載文件?

   

1
2
3
4
5
6
7
8
//創(chuàng)建了一個(gè)自定義的類加載器,該類加載器同時(shí)加載了所需要的jar包          
 ClassLoader loader = new JiveClassLoader(parent, libDir);
//設(shè)置自定義的類加載器為當(dāng)前線程的類加載器
Thread.currentThread().setContextClassLoader(loader);
//利用當(dāng)前線程的類加載器加載類文件,注意:這里需要帶包名寫全,不然項(xiàng)目中不通包中出現(xiàn)相同類文件就可能出現(xiàn)找不到的情況
Class containerClass = loader.loadClass(
                    "org.jivesoftware.openfire.XMPPServer");
            containerClass.newInstance();

 

到這里org.jivesoftware.openfire.starter.ServerStarter文件都閱讀完畢,ServerStarter中主要做了如下幾件事情:

  • 獲取classpath路徑

  • 把.pack文件轉(zhuǎn)換為jar文件

  • 獲取當(dāng)前線程的類加載器

  • 創(chuàng)建自定義類加載器,并加載jar文件跟zip文件到classpath中

  • 利用自定義的類加載器啟動(dòng)org.jivesoftware.openfire.XMPPServer類文件

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多

    日韩女优精品一区二区三区| 老司机精品视频在线免费看| 亚洲精品熟女国产多毛| 国产精品美女午夜福利| 国产精品丝袜美腿一区二区| 亚洲av日韩av高潮无打码| 午夜精品国产一区在线观看| 欧美一本在线免费观看| 欧美一级黄片欧美精品| 最近的中文字幕一区二区| 少妇一区二区三区精品| 欧美精品亚洲精品日韩专区| 亚洲欧美日本成人在线| 99精品人妻少妇一区二区人人妻| 99久久国产精品亚洲| 男人和女人草逼免费视频| 欧美日韩国产福利在线观看| 欧美三级精品在线观看| 极品熟女一区二区三区| 国产精品超碰在线观看| 中文字幕一区二区熟女| 亚洲国产成人久久99精品| 高清一区二区三区大伊香蕉| 尤物天堂av一区二区| 国产欧美一区二区久久| 国产亚洲二区精品美女久久| 久久精品久久久精品久久| 91久久国产福利自产拍| 丰满少妇高潮一区二区| 色婷婷国产精品视频一区二区保健 | 老司机精品一区二区三区| 老司机精品视频免费入口| 日韩精品区欧美在线一区| 污污黄黄的成年亚洲毛片| 国产欧美另类激情久久久| 欧洲自拍偷拍一区二区| 五月激情综合在线视频| 熟女少妇一区二区三区蜜桃| 国产精品一区二区三区激情| 欧美三级精品在线观看| 99久久免费看国产精品|