柚子快報激活碼778899分享:JVM-類加載
柚子快報激活碼778899分享:JVM-類加載
類加載過程
加載:加載是整個類加載的一個階段,他們是兩個不同的概念。在加載階段,主要是:
通過類的全限定名來獲取此類的二進制字節(jié)流。將這個字節(jié)流鎖代表的靜態(tài)存儲結構轉化為方法區(qū)的運行時數(shù)據(jù)結構。在堆中生成一個代表這個類的java.lang.Class對象,作為方法區(qū)類數(shù)據(jù)的訪問入口,這個過程需要類加載器參與。 連接:這個階段又可分為三個階段:
驗證:目的是確保Class文件的字節(jié)流中的信息符合JVM規(guī)范,防止運行后危害虛擬機自身安全。大致上從以下四個階段來完成驗證階段:
文件格式驗證:驗證字節(jié)流是否符合Class的規(guī)范,例如是否以魔數(shù)開頭,主、次版本號是否能被接受等等。元數(shù)據(jù)驗證:對類的元數(shù)據(jù)信息進行語義檢驗,保證其符合《Java語言規(guī)范》。字節(jié)碼驗證:通過數(shù)據(jù)流和控制流分析,確定程序語義是合法的、符合邏輯的。符號引用驗證:確保解析動作能正確執(zhí)行,例如通過全限定名是否能找到對應的類,符合引用中的類、字段、方法的訪問權限。 準備:準備階段是正式為類變量(即static修飾的變量)分配內存并設置類變量的初始值階段,即在方法區(qū)中分配這些變量所使用的內存空間。例如:public static int a = 100;
變量a在準備階段過后的初始值為0而不是100,而將a賦值為100的putstatic指令實際上是在程序被編譯后,存放在類構造器
符號引用 :簡單的理解就是字符串,在Class文件中的CONSTANT_Class_info、CONSTANT_Field_info等類型的常量。比如引用一個類,java.util.ArrayList 這就是一個符號引用,字符串引用的對象不一定被加載。直接引用 :指針或者地址偏移量。引用對象一定在內存,也就是說目標必定已經(jīng)被加載到內存中。 初始化:初始化階段就是執(zhí)行類加載器
類什么時候初始化? 在《JVM虛擬機規(guī)范中》沒有對加載階段進行強制約束,而對于初始化階段,卻有嚴格的規(guī)定,有且只有以下情況必須立即對類進行初始化(而加載、驗證、準備則自然在這之前開始):
通過new關鍵字創(chuàng)建對象訪問類的靜態(tài)變量,包括讀取和更新(被final修飾、在編譯時已經(jīng)在常量池中的除外)訪問類的靜態(tài)方法對某個類進行反射操作初始化子類會導致父類的的初始化執(zhí)行該類的main函數(shù) 除了以上幾種的主動引用,以下情況被動使用,不會觸發(fā)初始化:通過子類引用弗雷的靜態(tài)字段,不會導致子類初始化通過數(shù)組定義來引用類,不會觸發(fā)此類的初始化常量在編譯階段會存入調用類的常量池中,就比如我們在準備階段提到的使用final static修飾的變量。
使用:當JVM完成初始化階段之后,JVM便開始從入口方法開始執(zhí)行用戶的程序代碼。卸載:當用戶程序代碼執(zhí)行完畢后,JVM便開始銷毀創(chuàng)建的Class對象,最后負責運行的JVM也退出內存。
類加載器(ClassLoader)
虛擬機設計團隊把加載動作放到JVM外部實現(xiàn),以便讓應用程序決定如何獲取所需的類。實現(xiàn)這個動作的代碼被稱為“類加載器”(Class Loader)。對于 任意一個類,都必須由加載它的類加載器和這個類本身一起共同確立其在Java虛擬機中的唯一性 JVM提供了3中種類加載器:
啟動類加載器(Bootstrap):也叫引導類加載器,是由C++代碼實現(xiàn)的。負責加載JAVA_HOME\lib目錄的類庫。擴展類加載器(Extension):負責加載 JAVA_HOME\lib\ext 目錄中的應用程序類加載器(Application):負責加載用戶路徑(classpath)上的類庫
JVM通過雙親委派模型進行類的加載,當然我們也可以通過繼承 java.lang.ClassLoader實現(xiàn)自定義的類加載器。
值得注意的是:
AppClassLoader的父加載器是ExtClassLoader;ExtClassLoader的父加載器是Bootstrap;Bootstrap是根加載器。三者之間是沒有繼承關系的。AppClassLoader和ExtClassLoader都實現(xiàn)了抽象類ClassLoader。ClassLoader由一個parent字段,過設置該字段引用,指定父加載器。(是組合關系,即A has B)。AppClassLoader的parent指向ExtClassLoader,ExtClassLoader的parent指向null,(null的原因是因為Bootstrap是C++實現(xiàn)的,通過代碼中邏輯判斷來轉向Bootstrap)
雙親委派
如果一個類加載器收到了類加載的請求,它首先不會自己去嘗試加載這個類,而是把這個請求委派給父類加載器去完成,每一個層次的類加載器都是如此,因此所有的加載請求最終都應該傳送到最頂層的啟動類加載器中,只有當父加載器反饋自己無法完成這個加載請求(它的搜索范圍中沒有找到所需的類)時,子加載器才會嘗試自己去完成加載。
雙親委派的好處: 采用雙親委派的一個好處是比如加載位于rt.jar包中的類 java.lang.Object,不管是哪個加載器加載這個類,最終都是委托給頂層的啟動類加載器進行加載,這樣就保證了使用不同的類加載器最終得到的都是同樣一個Object對象。
雙親委派的好處: 采用雙親委派的一個好處是比如加載位于rt.jar包中的類 java.lang.Object,不管是哪個加載器加載這個類,最終都是委托給頂層的啟動類加載器進行加載,這樣就保證了使用不同的類加載器最終得到的都是同樣一個Object對象。
如何打破雙親委派:AppClassLoader和ExtClassLoader都實現(xiàn)了抽象類ClassLoader,在ClassLoader中有一個loadClass方法,就是實現(xiàn)雙親委派的代碼實現(xiàn),所以我們只要自定義的類加載器重新這個方法,就可以打破雙親委派機制。Tomcat就是打破了雙親委派。
柚子快報激活碼778899分享:JVM-類加載
推薦鏈接
本文內容根據(jù)網(wǎng)絡資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉載請注明,如有侵權,聯(lián)系刪除。