Tomcat載入類機制 – 我們到底能走多遠系列(14)

來源:互聯網
上載者:User
我們到底能走多遠系列(14)

扯淡:各位,你們的錢是省出來的嗎?前幾天一個同事(女)結婚,瞭解了下情況:男女一起買房接近80平方,實際房子是60平,四五十萬的首付吧,加上裝潢,男女全家,連外公外婆都出力出錢,搞定,圓滿買房結婚啦。大多數的我們都會走這麼一段路或已經走了這一段路。我不知道你們聽到這樣普通的八卦會是怎樣的感受。

剛看完《溫州一家人》的前兩集,買家送女兒出國學習,帶著兒子老婆以撿破爛開始溫州的新生活。雖然是電視劇,但上點年紀的都應該知道我們的上一輩很多人都有類似的魄力,對,因為那時候窮,窮怕了,拼了,現在一無所有,輸了,還是一無所有,不怕。

可是現在不一樣了,我們稍稍付出點努力就可以溫飽,再多付出點,還能接近傳說的小康。我們安逸,我們愛安逸,誰想打破安逸?誰也不想。所以我們寧願背負巨額的按揭,寧願接過父母的血汗,寧願丟掉自己的夢想,也要維護住著安逸。

我也不知道那個是好的那個是不好的,畢竟我也沒資格評價,但是這種矛盾是我們大多數人現在要面對的,睿智的你會怎麼度過?

--------------------------------------------------------------------------------------

前幾天利用了下午休時間去了家公司面試,有個問題說:如何來確保你寫的模組或方法是高品質的呢?

我當時說:通過單元測試,什麼review,效能測試。

回答方向不對。

          可讀性:代碼是否可讀易讀,對於一個團隊來說,編碼通訊協定是否一致,編碼風格是否一致;

   功能性:代碼正確得實現了商務邏輯;

   可維護性:代碼邏輯是有層次的,是容易修改的;

   高效性:代碼實現在時間和空間的使用上是高效的;

你會怎麼回答呢?

主題:

外圍知識:

1,jvm(java virtual mechanism)load class的基本原理 可以參考園子裡的文章

2,關於class.forName(String)
首先,我們是明白class檔案被jvm載入進來後,可以理解成以二進位形式存在記憶體中,每一個class我們可以通過包名和類名找到它。
其次,有了new這樣的操作,我們為什麼還需要這東西做什麼呢?
網上的一段代碼解釋了這個問題:

String className = readfromXMlConfig;//從xml 設定檔中獲得字串class c = Class.forName(className);factory = (ExampleInterface)c.newInstance(); 

我們可以看到被newInstance出來的執行個體只要是繼承ExampleInterface介面就可以滿足了,有一點需要記住的是,如果提供的類沒有繼承ExampleInterface,就會異常。
new關鍵字和newInstance()方法的區別:
newInstance: 弱類型。低效率。只能調用無參構造。(可是後面的代碼看來似乎能夠有參構造...)
new: 強型別。相對高效。能調用任何public構造。

3,載入類 java.lang.ClassLoader
我們可以通過調用ClassLoader的loadClass(String)方法來載入自己需要的類。
例子:

package code.loader;import java.net.URL;import java.net.URLClassLoader;import code.mytest.Test2;public class MyLoader1 {    public static void main(String[] args) throws Exception {        // 類名(注意:這裡是包含了包名沒有.class的形式)        String className = "code.mytest.Test2";        // class檔案位置        URL url = new URL("file:/D:/");        // ClassLoader執行個體        ClassLoader loader = new URLClassLoader(new URL[] {url});        // load進來之後是一個Class執行個體        Class c1 = loader.loadClass(className);        // 利用Class執行個體得到我們想要的執行個體        Test2 test = (Test2)c1.newInstance();        // 調用新執行個體的方法        test.sayYouILY();    }}

tomcat load class:

Tomcat需要自己載入web工程中的servlet類,我們頻繁發布修改後的工程,Tomcat就需要載入我們提供的代碼讓他跑起來。
在Http請求進入tomcat後,tomcat需要根據調用的servlet名把這個類先載入進來,這個過程是由tomcat的內部類:org.apache.catalina.loader.WebappLoader實現的,這個類實現了tomcat的org.apache.catalina.Loader介面,而WebappLoader中引用org.apache.catalina.loader.WebappClassLoader,而WebappClassLoader繼承了URLClassLoader

WebappLoader用getClassLoader()方法向外提供出一個自訂的ClassLoader,為什麼這麼說呢?來看下源碼:
1,WebappLoader中的start()方法中會調用下面兩句:

classLoader = createClassLoader();//這個是內建的private方法classLoader.setResources(container.getResources());

2,createClassLoader源碼:

private WebappClassLoader createClassLoader()        throws Exception {        // 這個loaderClass是啥東西呀?        // 其實是WebappClassLoader私人變數,定義成:private String loaderClass ="org.apache.catalina.loader.WebappClassLoader";        Class clazz = Class.forName(loaderClass);        WebappClassLoader classLoader = null;        if (parentClassLoader == null) {            parentClassLoader = container.getParentClassLoader();        }        Class[] argTypes = { ClassLoader.class };        Object[] args = { parentClassLoader };        // API:返回一個 Constructor 對象,它反映此 Class 對象所表示的類的指定公用構造方法。parameterTypes 參數是 Class 對象的一個數組,這些 Class 對象按聲明順序標識構造方法的形式參數類型。        Constructor constr = clazz.getConstructor(argTypes);        //使用此 Constructor 對象表示的構造方法來建立該構造方法的聲明類的新執行個體,並用指定的初始化參數初始化該執行個體。(這樣做是不是達到了前面提到的有參構造呢)        classLoader = (WebappClassLoader) constr.newInstance(args);        return classLoader;    }

3,通過WebappClassLoader,可以控制已經載入的類不用再重複操作。
每一個通過WebappClassLoader載入的類都會被org.apache.catalina.loader.ResourceEntry記錄下來

package org.apache.catalina.loader;import java.net.URL;import java.security.cert.Certificate;import java.util.jar.Manifest;public class ResourceEntry {    public long lastModified = -1;    public byte[] binaryContent = null;// 類是以byte數群組類型被儲存在記憶體中    public volatile Class loadedClass = null;    public URL source = null;// URL名稱    public URL codeBase = null;    public Manifest manifest = null;    public Certificate[] certificates = null;}

在WebappClassLoader裡有一個Map來記錄已經被載入的類

 /**     * The cache of ResourceEntry for classes and resources we have loaded,     * keyed by resource name.     */    protected HashMap resourceEntries = new HashMap();

這樣一來當需要載入新類是我們先在這個map裡面去找一下
來看一下findResource方法的源碼:

public URL findResource(final String name) {        if (log.isDebugEnabled())            log.debug("    findResource(" + name + ")");        URL url = null;        if (hasExternalRepositories && searchExternalFirst)            url = super.findResource(name);        if (url == null) {            // 去傳說中的記憶體裡找是否已經載入            ResourceEntry entry = (ResourceEntry) resourceEntries.get(name);            // 沒有載入過            if (entry == null) {                if (securityManager != null) {                    PrivilegedAction<ResourceEntry> dp =                        new PrivilegedFindResourceByName(name, name);                    entry = AccessController.doPrivileged(dp);                } else {                    entry = findResourceInternal(name, name);                }            }            // 載入過            if (entry != null) {                url = entry.source;            }        }        if ((url == null) && hasExternalRepositories && !searchExternalFirst)            url = super.findResource(name);        if (log.isDebugEnabled()) {            if (url != null)                log.debug("    --> Returning '" + url.toString() + "'");            else                log.debug("    --> Resource not found, returning null");        }        // 返回URL        return (url);    }

 

總結:

1,tomcat自訂自己的class loader,值得借鑒,還沒有研究核心的實作類別,因為還需要學習下自訂loader的實現。

2,用hashmap來存需要即時查詢的資源,很實用。

 

讓我們繼續前行

----------------------------------------------------------------------

 

努力不一定成功,但不努力肯定不會成功。
共勉

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.