classloader總結

classloader是什麼java

      個人理解classloader就是加載咱們的類到內存的類,他主要就是尋找資源,即找到在他能搜索到的路徑中,有沒有咱們的類。有的話就加載到內存。web

系統的classloader數組

系統的classloader有三種tomcat

Bootstrap ClassLoader     負責加載java基礎類,主要是 %JRE_HOME/lib/ 目錄下的rt.jar、resources.jar、charsets.jar和class等服務器

Extension ClassLoader      負責加載java擴展類,主要是 %JRE_HOME/lib/ext 目錄下的jar和class
app

App ClassLoader           負責加載當前java應用的classpath中的全部類。jvm

雙親委託機制ide

    系統的classloader實行的是雙親委託機制,雙親委託機制就是在加載類的時候先去父類(此處的父類不是繼承裏面的父類,雙親委託機制是組合)裏查找,若是父類加載到了就算子類的能夠在本身的路徑下找到,也不能加載。只會從父類中取到加到後的class。這樣的好處就是不會重複加載類。測試

    此處只是說系統的classloader,由於你本身寫的classloader不必定要遵循這個機制,並且有些狀況必須不能遵循,例如tomcat等服務器,加載的時候不會遵循雙親委託(他的classloder是本身實現的),他是優先本身加載,本身加載不到纔會委託父類加載,他是必須容許,相同的類會被重複加載。由於你兩個web應用用到了相同的類,加載的時候是加載了一個web應用的類,那麼解部署的時候必須不能刪除該類,由於另外一個web應用還在用。
加密

本身寫classloader

    知道這麼多機制,確定是爲了本身寫classloader,本身寫的classloder有不少用處,例如本身作點字節碼增長功能(固然javaagent也能作),作對類的加密解密功能等等。

    java提供了一個類幫助咱們實現classloader,這個類是URLClassLoader,咱們只須要繼承這個類,覆寫loadClass方法就能夠,他必須調用父類的構造方法,傳遞url數組,這裏的url數組裏面就是這個classloader能尋找的路徑。若是在你的路徑中尋找,這是你須要實現的邏輯,大部分仍是直接調用父類的方法,由於他已經知道路徑了,不少時候你不須要去處理,java已經幫你實現了。

public class Loader extends URLClassLoader {

	public Loader(URL[] urls) {
		super(urls);
	}

	@Override
	public Class<?> loadClass(String name) throws ClassNotFoundException {
		return super.loadClass(name);
	}

}

這就是一個遵循雙親委託機制的classloader。很簡單。

    如何破壞雙親委託呢?這個你們已經明瞭了。就是改loadClass方法里加載的過程。舉個例子,若是你先寫個本身查找的方法放在super.loadClass(name)以前,那麼已經不是默認的雙親機制了。這裏必須介紹一個方法,就是加載類到內存的方法defineclass。具體再怎麼加載,這個就不須要咱們管了。由於確實用不到那麼多。

如何使用classloader

Thread.currentThread().setContextClassLoader(loader);

    經過設置當前線程classloader來更改classloader,這種方法最經常使用,這樣就簡單的更改了classloader,之後這個線程加載類就靠你設置的classloader,再也不直接是appclassloader。

    第二種用法用來測試classloader不錯,就是直接調用你本身寫的classloder的loadclass方法獲取Class對象。

本身寫的classloader是誰來加載?

    這個不用想了,是app classloader,雖然你是classloader,可是對jvm而言,他只是個字節碼文件罷了。他在app classloader的加載路徑上。

類A非類A

    因爲classloader會出現一個頗有意思的問題,相似古代白馬非馬的問題。舉個例子當一個類被兩個classloader加載時,第一個classloader產生類A對象,傳遞給另外一個classloderA的聲明,結果就出現轉換出錯的問題。

    在java裏,只有被同一個classloader加載的類纔會被認爲是同一個類,兩個classloader都加載了類A,那麼就會被認爲是兩個徹底不相干的類。(可是兩個類A都繼承B,用B對象的引用去接收賦值沒問題,只是兩個相同的類賦值這個類的聲明纔會有這個問題)。
總結

    classloader的重點是你加載類的路徑和文件,若是保證了路徑和文件,那麼classloader也就沒啥了,由於剩下的徹底依靠父類方法就能夠,除非你的處理須要修改其餘方法。

相關文章
相關標籤/搜索