有時候,根據自己專案的需求,需要重新實現屬於自己的類載入器,以滿足專案的靈活性和擴充套件性,下面我們就來實現自己的類載入器.
實現自己的類載入器必須首先繼承乙個父類載入器.
編寫乙個類載入器會涉及到以下幾個方法:
1. findclass(string name) 根據類的路徑查詢類,必須重寫的方法
2.defineclass(string name, byte b, int off, int len) 由父類實現,直接呼叫
3.loadclass(string name)首先呼叫父類的findclass方法找,找不到則呼叫自身重寫的findclass方法找,也不需要我們實現.loadclass(string name)缺省會呼叫loadclass(name,false)方法,表示只載入,不發生連線操作.jdk的classloader類的loadclass(string name,boolean resolve)方法的實現如下:
protected synchronized class<?> loadclass(string name, boolean resolve) throws classnotfoundexception
else
} catch (classnotfoundexception e)
} if (resolve)
return c;
}
可以看出classloader採用了模版模式,在父類載入器載入不到想要的類時,採用自己實現的方法.
自己寫的類載入器及測試**如下:
public class myclassloader extends classloader
byte bytes = os.tobytearray();
os.flush();
return defineclass(name, bytes, 0, bytes.length);
} catch (exception e) finally catch (ioexception e1)
} return null;
} @suppresswarnings("unchecked")
public static void main(string args) catch (exception e)
}}
hellowolrd類如下:
public class helloworld
}
我把helloworld類放在c:/bin/目錄下.
最後談一下loadclass()和forname()的區別.
從上可以看出呼叫loadclass(name),相當於呼叫loadclass(name,false),表示只載入類,不連線初始化類,呼叫newinstance()才真正完成連線初始化操作.
class.forname("***x")等同於class.forname("***x",true,loader).true,表示載入例項的同時也載入靜態初始化區塊;false,表示只會載入該類別,但不會呼叫其靜態初始化區塊,只有等到整個程式第一次例項化某個類時,靜態初始化區塊才會被呼叫
在大多情況下loadclass()和forname()可以互用, 可以把classloader.loadclass()看成是更底層的操作.在某些必須初始化類的場合,比如載入jdbc驅動,只能使用forname()方法了
從上可以看出,實現自己的類載入器相當簡單,只要繼承乙個父類載入器,重寫findclass方法就可以了.
類載入器載入順序
先上 public class parent static public parent public static void staticmethod1 public static void staticmethod2 測試類 public static void main string args ...
JVM 類載入機制 類載入器
類宣告週期 檔案格式驗證 基於二進位製流,只有這一步是基於二進位製流,後續步驟都是基於方法區資料 1.魔數 cafe babe 開頭 2.主次版本是否在當前jvm支援範圍 3.常量池的常量是否不被支援 4.很多很多規範 元資料驗證 1.類是否有父類,object 2.匪類是否繼承了被final修飾的...
JVM類載入機制 類載入器
一 概念 通過乙個類的全限定名來獲取描述此類的二進位制位元組流 實現這個動作的 模組成為 類載入器。4 雙親委派模型 1 定義 除了頂層的啟動類載入器外,其餘的類載入器都應當有自己的父類載入器,且載入器之間的父子關係一般不會繼承,而是使用組合關係來復用父載入器的 2 工作過程 如果乙個類載入器收到了...