java類加載機(jī)制與反射

一椅您、Java類加載機(jī)制

1.概述

Class文件由類裝載器裝載后,在JVM中將形成一份描述Class結(jié)構(gòu)的元信息對象寡键,通過該元信息對象可以獲知Class的結(jié)構(gòu)信息:如構(gòu)造函數(shù)襟沮,屬性和方法等,Java允許用戶借由這個Class相關(guān)的元信息對象間接調(diào)用Class對象的功能昌腰。

虛擬機(jī)把描述類的數(shù)據(jù)從class文件加載到內(nèi)存开伏,并對數(shù)據(jù)進(jìn)行校驗,轉(zhuǎn)換解析和初始化遭商,最終形成可以被虛擬機(jī)直接使用的Java類型固灵,這就是虛擬機(jī)的類加載機(jī)制。

2.工作機(jī)制

類裝載器就是尋找類的字節(jié)碼文件劫流,并構(gòu)造出類在JVM內(nèi)部表示的對象組件巫玻。在Java中,類裝載器把一個類裝入JVM中祠汇,要經(jīng)過以下步驟:

(1) 裝載:查找和導(dǎo)入Class文件仍秤;

(2) 鏈接:把類的二進(jìn)制數(shù)據(jù)合并到JRE中;

(a)校驗:檢查載入Class文件數(shù)據(jù)的正確性可很;

(b)準(zhǔn)備:給類的靜態(tài)變量分配存儲空間诗力;

(c)解析:將符號引用轉(zhuǎn)成直接引用;

(3) 初始化:對類的靜態(tài)變量我抠,靜態(tài)代碼塊執(zhí)行初始化操作

Java程序可以動態(tài)擴(kuò)展是由運(yùn)行期動態(tài)加載和動態(tài)鏈接實(shí)現(xiàn)的苇本;比如:如果編寫一個使用接口的應(yīng)用程序袜茧,可以等到運(yùn)行時再指定其實(shí)際的實(shí)現(xiàn)(多態(tài)),解析過程有時候還可以在初始化之后執(zhí)行瓣窄;比如:動態(tài)綁定(多態(tài))笛厦;

【類初始化】

(1) 遇到new、getstatic俺夕、putstatic或invokestatic這4條字節(jié)碼指令時裳凸,如果類沒有進(jìn)行過初始化,則需要先觸發(fā)其初始化劝贸。生成這4條指令的最常見的Java代碼場景是:使用new關(guān)鍵字實(shí)例化對象的時候登舞,讀取或設(shè)置一個類的靜態(tài)字段(被final修飾、已在編譯期把結(jié)果放入常量池的靜態(tài)字段除外)的時候悬荣,以及調(diào)用一個類的靜態(tài)方法的時候。

(2) 使用java.lang.reflect包的方法對類進(jìn)行反射調(diào)用的時候疙剑,如果類沒有進(jìn)行過初始化氯迂,則需要先觸發(fā)其初始化。

(3) 當(dāng)初始化一個類的時候言缤,如果發(fā)現(xiàn)其父類還沒有進(jìn)行過初始化嚼蚀,則需要先觸發(fā)其父類的初始化。

(4)當(dāng)虛擬機(jī)啟動時管挟,用戶需要指定一個要執(zhí)行的主類(包含main()方法的那個類)轿曙,虛擬機(jī)會先初始化這個主類。

只有上述四種情況會觸發(fā)初始化僻孝,也稱為對一個類進(jìn)行主動引用导帝,除此以外,所有其他方式都不會觸發(fā)初始化穿铆,稱為被動引用

代碼清單1

上述代碼運(yùn)行后您单,只會輸出【---SuperClass init】, 而不會輸出【SubClass init】,對于靜態(tài)字段,只有直接定義這個字段的類才會被初始化,因此荞雏,通過子類來調(diào)用父類的靜態(tài)字段虐秦,只會觸發(fā)父類的初始化,但是這是要看不同的虛擬機(jī)的不同實(shí)現(xiàn)。

代碼清單2

此處不會引起SuperClass的初始化凤优,但是卻觸發(fā)了【[Ltest.SuperClass】的初始化悦陋,通過arr.toString()可以看出,對于用戶代碼來說筑辨,這不是一個合法的類名稱俺驶,它是由虛擬機(jī)自動生成的,直接繼承于Object的子類棍辕,創(chuàng)建動作由字節(jié)碼指令newarray觸發(fā),此時數(shù)組越界檢查也會伴隨數(shù)組對象的所有調(diào)用過程痒钝,越界檢查并不是封裝在數(shù)組元素訪問的類中秉颗,而是封裝在數(shù)組訪問的xaload,xastore字節(jié)碼指令中.

代碼清單3

對常量ConstClass.value 的引用實(shí)際都被轉(zhuǎn)化為NotInitialization類對自身常量池的引用,這兩個類被編譯成class后不存在任何聯(lián)系送矩。

【裝載】

在裝載階段蚕甥,虛擬機(jī)需要完成以下3件事情

(1) 通過一個類的全限定名來獲取定義此類的二進(jìn)制字節(jié)流

(2) 將這個字節(jié)流所代表的靜態(tài)存儲結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)的運(yùn)行時數(shù)據(jù)結(jié)構(gòu)

(3) 在Java堆中生成一個代表這個類的java.lang.Class對象,作為方法區(qū)這些數(shù)據(jù)的訪問入口栋荸。

虛擬機(jī)規(guī)范中并沒有準(zhǔn)確說明二進(jìn)制字節(jié)流應(yīng)該從哪里獲取以及怎樣獲取,這里可以通過定義自己的類加載器去控制字節(jié)流的獲取方式菇怀。

【驗證】

虛擬機(jī)如果不檢查輸入的字節(jié)流,對其完全信任的話晌块,很可能會因為載入了有害的字節(jié)流而導(dǎo)致系統(tǒng)奔潰爱沟。

【準(zhǔn)備】

準(zhǔn)備階段是正式為類變量分配并設(shè)置類變量初始值的階段,這些內(nèi)存都將在方法區(qū)中進(jìn)行分配,需要說明的是:

這時候進(jìn)行內(nèi)存分配的僅包括類變量(被static修飾的變量),而不包括實(shí)例變量,實(shí)例變量將會在對象實(shí)例化時隨著對象一起分配在Java堆中;這里所說的初始值“通常情況”是數(shù)據(jù)類型的零值匆背,假如:

public static int value = 123;

value在準(zhǔn)備階段過后的初始值為0而不是123,而把value賦值的putstatic指令將在初始化階段才會被執(zhí)行

二呼伸、類加載器與雙親委派模型

類加載器

(1) Bootstrap ClassLoader : 將存放于\lib目錄中的,或者被-Xbootclasspath參數(shù)所指定的路徑中的钝尸,并且是虛擬機(jī)識別的(僅按照文件名識別括享,如 rt.jar 名字不符合的類庫即使放在lib目錄中也不會被加載)類庫加載到虛擬機(jī)內(nèi)存中。啟動類加載器無法被Java程序直接引用

(2) Extension ClassLoader : 將\lib\ext目錄下的珍促,或者被java.ext.dirs系統(tǒng)變量所指定的路徑中的所有類庫加載铃辖。開發(fā)者可以直接使用擴(kuò)展類加載器。

(3) Application ClassLoader : 負(fù)責(zé)加載用戶類路徑(ClassPath)上所指定的類庫,開發(fā)者可直接使用猪叙。

雙親委派模型

工作過程:如果一個類加載器接收到了類加載的請求娇斩,它首先把這個請求委托給他的父類加載器去完成,每個層次的類加載器都是如此穴翩,因此所有的加載請求都應(yīng)該傳送到頂層的啟動類加載器中犬第,只有當(dāng)父加載器反饋?zhàn)约簾o法完成這個加載請求(它在搜索范圍中沒有找到所需的類)時,子加載器才會嘗試自己去加載芒帕。

好處:java類隨著它的類加載器一起具備了一種帶有優(yōu)先級的層次關(guān)系瓶殃。例如類java.lang.Object,它存放在rt.jar中副签,無論哪個類加載器要加載這個類遥椿,最終都會委派給啟動類加載器進(jìn)行加載,因此Object類在程序的各種類加載器環(huán)境中都是同一個類淆储。相反冠场,如果用戶自己寫了一個名為java.lang.Object的類,并放在程序的Classpath中本砰,那系統(tǒng)中將會出現(xiàn)多個不同的Object類碴裙,java類型體系中最基礎(chǔ)的行為也無法保證,應(yīng)用程序也會變得一片混亂。

java.lang.ClassLoader中幾個最重要的方法:

//加載指定名稱(包括包名)的二進(jìn)制類型舔株,供用戶調(diào)用的接口

public Class loadClass(String name);

//加載指定名稱(包括包名)的二進(jìn)制類型莺琳,同時指定是否解析(但是,這里的resolve參數(shù)不一定真正能達(dá)到解析的效果)载慈,供繼承用

protected synchronized Class loadClass(String name, boolean resolve);

protected Class findClass(String name)

//定義類型惭等,一般在findClass方法中讀取到對應(yīng)字節(jié)碼后調(diào)用,可以看出不可繼承(說明:JVM已經(jīng)實(shí)現(xiàn)了對應(yīng)的具體功能办铡,解析對應(yīng)的字節(jié)碼辞做,產(chǎn)生對應(yīng)的內(nèi)部數(shù)據(jù)結(jié)構(gòu)放置到方法區(qū),所以無需覆寫寡具,直接調(diào)用就可以了)

protected final Class defineClass(String name, byte[] b, int off, int len) throws ClassFormatError{}

ClassFormatError{}如下是實(shí)現(xiàn)雙親委派模型的主要代碼:

三秤茅、反射

Reflection機(jī)制允許程序在正在執(zhí)行的過程中,利用Reflection APIs取得任何已知名稱的類的內(nèi)部信息童叠,包括:package框喳、 type parameters、 superclass厦坛、 implemented interfaces五垮、 inner classes、 outer classes粪般、 fields、 constructors污桦、 methods亩歹、 modifiers等,并可以在執(zhí)行的過程中凡橱,動態(tài)生成instances小作、變更fields內(nèi)容或喚起methods。

1稼钩、獲取構(gòu)造方法

Class類提供了四個public方法顾稀,用于獲取某個類的構(gòu)造方法。

Constructor getConstructor(Class[] params)

根據(jù)構(gòu)造函數(shù)的參數(shù)坝撑,返回一個具體的具有public屬性的構(gòu)造函數(shù)

Constructor getConstructors()

返回所有具有public屬性的構(gòu)造函數(shù)數(shù)組

Constructor getDeclaredConstructor(Class[] params)

根據(jù)構(gòu)造函數(shù)的參數(shù)静秆,返回一個具體的構(gòu)造函數(shù)(不分public和非public屬性)

Constructor getDeclaredConstructors()

返回該類中所有的構(gòu)造函數(shù)數(shù)組(不分public和非public屬性)

2、獲取類的成員方法

與獲取構(gòu)造方法的方式相同巡李,存在四種獲取成員方法的方式抚笔。

Method getMethod(String name, Class[] params)

根據(jù)方法名和參數(shù),返回一個具體的具有public屬性的方法

Method[] getMethods()

返回所有具有public屬性的方法數(shù)組

Method getDeclaredMethod(String name, Class[] params)

根據(jù)方法名和參數(shù)侨拦,返回一個具體的方法(不分public和非public屬性)

Method[] getDeclaredMethods()

返回該類中的所有的方法數(shù)組(不分public和非public屬性)

3殊橙、獲取類的成員變量(成員屬性)

存在四種獲取成員屬性的方法

Field getField(String name)

根據(jù)變量名,返回一個具體的具有public屬性的成員變量

Field[] getFields()

返回具有public屬性的成員變量的數(shù)組

Field getDeclaredField(String name)

根據(jù)變量名,返回一個成員變量(不分public和非public屬性)

Field[] getDelcaredFields()

返回所有成員變量組成的數(shù)組(不分public和非public屬性)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末膨蛮,一起剝皮案震驚了整個濱河市叠纹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌敞葛,老刑警劉巖誉察,帶你破解...
    沈念sama閱讀 211,817評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異制肮,居然都是意外死亡冒窍,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評論 3 385
  • 文/潘曉璐 我一進(jìn)店門豺鼻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來综液,“玉大人,你說我怎么就攤上這事儒飒∶ǎ” “怎么了?”我有些...
    開封第一講書人閱讀 157,354評論 0 348
  • 文/不壞的土叔 我叫張陵桩了,是天一觀的道長附帽。 經(jīng)常有香客問我,道長井誉,這世上最難降的妖魔是什么蕉扮? 我笑而不...
    開封第一講書人閱讀 56,498評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮颗圣,結(jié)果婚禮上喳钟,老公的妹妹穿的比我還像新娘。我一直安慰自己在岂,他們只是感情好奔则,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蔽午,像睡著了一般易茬。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上及老,一...
    開封第一講書人閱讀 49,829評論 1 290
  • 那天抽莱,我揣著相機(jī)與錄音,去河邊找鬼骄恶。 笑死岸蜗,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的叠蝇。 我是一名探鬼主播璃岳,決...
    沈念sama閱讀 38,979評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼年缎,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了铃慷?” 一聲冷哼從身側(cè)響起单芜,我...
    開封第一講書人閱讀 37,722評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎犁柜,沒想到半個月后洲鸠,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,189評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡馋缅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評論 2 327
  • 正文 我和宋清朗相戀三年扒腕,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片萤悴。...
    茶點(diǎn)故事閱讀 38,654評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡瘾腰,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出覆履,到底是詐尸還是另有隱情蹋盆,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布硝全,位于F島的核電站栖雾,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏伟众。R本人自食惡果不足惜析藕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望凳厢。 院中可真熱鬧账胧,春花似錦、人聲如沸数初。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽泡孩。三九已至,卻和暖如春寺谤,著一層夾襖步出監(jiān)牢的瞬間仑鸥,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評論 1 266
  • 我被黑心中介騙來泰國打工变屁, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留眼俊,地道東北人。 一個月前我還...
    沈念sama閱讀 46,382評論 2 360
  • 正文 我出身青樓粟关,卻偏偏與公主長得像疮胖,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評論 2 349

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理澎灸,服務(wù)發(fā)現(xiàn)院塞,斷路器,智...
    卡卡羅2017閱讀 134,633評論 18 139
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法性昭,類相關(guān)的語法拦止,內(nèi)部類的語法檬某,繼承相關(guān)的語法串远,異常的語法,線程的語...
    子非魚_t_閱讀 31,598評論 18 399
  • 原文鏈接:http://iaspecwang.iteye.com/blog/1931043 一.概述 定義:虛擬機(jī)...
    晴天哥_王志閱讀 6,761評論 1 35
  • 女人如水箕速,嬌羞嫣然,溫情浪漫朋譬,感性里永遠(yuǎn)有繾繾綣綣的愛盐茎;理性里永遠(yuǎn)有默默無言的舍。女人的心事徙赢,只有自己才能讀懂字柠,用...
    TWE閱讀 3,098評論 0 0
  • 如果世界上有那么一個人出現(xiàn)過,那么其他人都會變成將就狡赐。而我不愿意將就窑业。-何以琛。 我最喜歡的小說枕屉,沒有之一...
    小鹿_045a閱讀 204評論 0 1